react 中useState 使用Immer 简化数据更改操作数组、对象

如果你不想改变你的状态结构,你可能更喜欢嵌套传播的捷径。Immer 是一个流行的库,它允许你使用方便但可变的语法进行编写,并负责为你生成副本。使用 Immer,你编写的代码看起来就像你是 "打破规则" 并且正在改变一个对象:

安装

复制代码
npm install use-immer --save

使用

复制代码
然后用 import { useImmer } from 'use-immer' 替换 import { useState } from 'react'
iimport { useImmer } from 'use-immer';

export default function Form() {
  const [person, updatePerson] = useImmer({
    name: 'Niki de Saint Phalle',
    artwork: {
      title: 'Blue Nana',
      city: 'Hamburg',
      image: 'https://i.imgur.com/Sd1AgUOm.jpg',
    }
  });

  function handleNameChange(e) {
    updatePerson(draft => {
      draft.name = e.target.value;
    });
  }

  function handleTitleChange(e) {
    updatePerson(draft => {
      draft.artwork.title = e.target.value;
    });
  }

  function handleCityChange(e) {
    updatePerson(draft => {
      draft.artwork.city = e.target.value;
    });
  }

  function handleImageChange(e) {
    updatePerson(draft => {
      draft.artwork.image = e.target.value;
    });
  }

  return (
    <>
      <label>
        Name:
        <input
          value={person.name}
          onChange={handleNameChange}
        />
      </label>
      <label>
        Title:
        <input
          value={person.artwork.title}
          onChange={handleTitleChange}
        />
      </label>
      <label>
        City:
        <input
          value={person.artwork.city}
          onChange={handleCityChange}
        />
      </label>
      <label>
        Image:
        <input
          value={person.artwork.image}
          onChange={handleImageChange}
        />
      </label>
      <p>
        <i>{person.artwork.title}</i>
        {' by '}
        {person.name}
        <br />
        (located in {person.artwork.city})
      </p>
      <img 
        src={person.artwork.image} 
        alt={person.artwork.title}
      />
    </>
  );
}

更改数组

复制代码
import { useState } from 'react';
import { useImmer } from 'use-immer';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [myList, updateMyList] = useImmer(
    initialList
  );
  const [yourList, updateYourList] = useImmer(
    initialList
  );

  function handleToggleMyList(id, nextSeen) {
    updateMyList(draft => {
      const artwork = draft.find(a =>
        a.id === id
      );
      artwork.seen = nextSeen;
    });
  }

  function handleToggleYourList(artworkId, nextSeen) {
    updateYourList(draft => {
      const artwork = draft.find(a =>
        a.id === artworkId
      );
      artwork.seen = nextSeen;
    });
  }

  return (
    <>
      <h1>Art Bucket List</h1>
      <h2>My list of art to see:</h2>
      <ItemList
        artworks={myList}
        onToggle={handleToggleMyList} />
      <h2>Your list of art to see:</h2>
      <ItemList
        artworks={yourList}
        onToggle={handleToggleYourList} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}
相关推荐
Fighting_p18 小时前
【导出】前端 js 导出下载文件时,文件名前后带下划线问题
开发语言·前端·javascript
WYiQIU18 小时前
从今天开始备战1月中旬的前端寒假实习需要准备什么?(飞书+github+源码+题库含答案)
前端·javascript·面试·职场和发展·前端框架·github·飞书
skywalk816318 小时前
waveterm一款 跨平台、基于 Web 的现代终端
前端·waveterm
AI分享猿18 小时前
新手跨境电商实测:Apache 搭站,雷池 WAF 零基础部署
安全·web安全·react.js·网络安全·开源·apache
摸鱼少侠梁先生18 小时前
通过接口获取字典的数据进行渲染
前端·javascript·vue.js
大卡拉米18 小时前
前端组件库 PDF、word、Excel预览
前端·pdf·word
2401_8603195218 小时前
react-native-calendarsReact Native库来帮助你处理日期和时间,实现鸿蒙跨平台开发日历组件
react native·react.js·harmonyos
赵财猫._.18 小时前
React Native鸿蒙开发实战(九):复杂业务场景实战与架构设计
react native·react.js·harmonyos
小满zs18 小时前
Next.js第十四章(缓存策略)
前端
低保和光头哪个先来19 小时前
CSS+JS实现单例老虎机切换图片动画
前端·javascript·css