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>
  );
}
相关推荐
非优秀程序员23 分钟前
第10章 千团出世|《互联网产品恩仇录》
前端
非优秀程序员28 分钟前
第11章 小高在对面|《互联网产品恩仇录》
前端
非优秀程序员28 分钟前
第14章 只剩美团|《互联网产品恩仇录》
前端
非优秀程序员30 分钟前
第09章 老乡何必为难老乡|《互联网产品恩仇录》
前端
非优秀程序员40 分钟前
第03章 三大门户,烽烟起于瀛海威|《互联网产品恩仇录》
前端
曦樂~5 小时前
【Web Development】02 CSS
前端·css
风骏时光牛马5 小时前
后端服务接口开发与数据逻辑处理
前端
东鹏特饮5 小时前
经典打砖块(Breakout)游戏
前端·css·css3
IT_陈寒5 小时前
Vite的HMR把我整不会了:一个生产环境的热更新坑
前端·人工智能·后端
Mh5 小时前
如何使用双缓冲优化视频切换
前端