如果你不想改变你的状态结构,你可能更喜欢嵌套传播的捷径。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:<inputvalue={person.name}onChange={handleNameChange}/></label><label>Title:<inputvalue={person.artwork.title}onChange={handleTitleChange}/></label><label>City:<inputvalue={person.artwork.city}onChange={handleCityChange}/></label><label>Image:<inputvalue={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><ItemListartworks={myList}onToggle={handleToggleMyList} /><h2>Your list of art to see:</h2><ItemListartworks={yourList}onToggle={handleToggleYourList} /></>);
}function ItemList({ artworks, onToggle }) {return (<ul>{artworks.map(artwork => (<li key={artwork.id}><label><inputtype="checkbox"checked={artwork.seen}onChange={e => {onToggle(artwork.id,e.target.checked);}}/>{artwork.title}</label></li>))}</ul>);
}