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>
  );
}
相关推荐
bugcome_com12 小时前
JWT 知识小课堂:从入门到精通,一文吃透 JSON Web Token
前端·json
To_OC13 小时前
写了三天 Next.js,我的 React 世界观被拆了又装回去
前端·全栈·next.js
独泪了无痕13 小时前
viewer.js 安装与配置指南:实现图片预览功能
前端·vue.js
Fluxart.ai15 小时前
电商商品图审核怎么自动化?规则引擎、人工复核与发布门禁
java·前端·自动化
why技术15 小时前
AI 写的文章,可能都带着手敲一遍都去不掉的“隐形水印”。
前端·人工智能·后端
愚公搬代码16 小时前
【愚公系列】《Android应用案例开发大全》016-LBS类应用掌上杭州(辅助工具类的开发)
android·前端
CodeSheep16 小时前
又一个华为天才少年,离职了!
前端·后端·程序员
kyriewen16 小时前
面试官说"打开你的AI工具"——我才发现,他考的根本不是写代码
前端·人工智能·面试
IT_陈寒17 小时前
Vue的双向绑定把我坑惨了,原来这个场景不能用
前端·人工智能·后端
hunterandroid17 小时前
[Android 从零到一] Compose LazyColumn 性能优化:key、稳定性与重组治理
android·前端