主要困惑的内容在两个 onClick 事件里,一个对于 state 是 immutable 的,另一个不是,但是效果是相同的。疑惑的点在于
- 两种写法是否都可以,第一种写法会不会导致 bug(比如 react18 cm 模式下)
- 如果两个写法都可以,是不是说明 react 本身并不强依赖 state 的 immutable ,只需要让 newState!==oldState ,也就是引用改变(非 js 基础类型),然后 newState 丢到 setState 里面去 react 都能正常 render
import { useState } from "react" function App() { let [personList, setPersonList] = useState([{ name: "jack", age: 18 }]) const onClick1 = () => { let newState = [...personList] newState.push({ name: "kk", age: 1 }) // 这里相当于直接修改了 personList[0].name 上的值,对于 personList 这个 state 没有做到 immutable newState[0].name = "ddddddd" setPersonList(newState) } const onClick2 = () => { setPersonList([ { // 这里先复制一遍 personList[0],再复制,personList 这个 state 在过程中是只读的,是 immutable ...personList[0], name: "ddddddd", }, ...personList.slice(1), { name: "kk", age: 1 }, ]) } return ( <div className="App"> <button OnClick={onClick1}>add1</button> <button OnClick={onClick2}>add2</button> {personList.map((item, index) => { return <div key={index}>{item.name}</div> })} </div> ) } export default App 补充一下上述语境中 immutable 的定义,以常见的 immutable 库 immer 为例,可以看到执行函数,返回 new1 后,old 的值是不变的,这样可以认为 old 是 immutable 的
import { produce } from "immer" const old = [{ name: "jack", age: 18 }] const new1 = produce(old, (state) => { state[0].name = "ddddddd" state.push({ name: "kk", age: 1 }) }) console.log("原始值", old) // 原始值 [ { name: 'jack', age: 18 } ] console.log("新值", new1) // 新值 [ { name: 'ddddddd', age: 18 }, { name: 'kk', age: 1 } ] 