不可变性 意味着永远不要直接修改 state — 相反,你创建一个包含变化的新 object/array。这是 React、Redux 和类似工具检测变化并正确更新 UI 的核心机制。
直接修改的问题
jsx
() {
items.(item);
(items);
}
() {
([...items, item]);
}
React(和 Redux)通过比较引用(oldState === newState)而不是深层内容来检测变化 — 这是出于性能考虑。如果你直接修改,引用保持不变,所以框架认为没有任何改变并跳过重新渲染。
// arrays
setItems([...items, newItem]); // add
setItems(items.filter(i => i.id !== id)); // remove
setItems(items.map(i => i.id === id ? { ...i, done: true } : i)); // update one
// objects
setUser({ ...user, name: "Bob" }); // update a field
setUser({ ...user, address: { ...user.address, city: "NY" } }); // nested update
spread 操作符创建浅层副本;对于嵌套数据,你需要复制你修改的每一层。
✓ Reliable change detection → correct, efficient re-renders (reference equality)
✓ Enables performance optimizations (React.memo, OnPush, useMemo) that compare references
✓ Predictable state — old state is never altered, easing debugging
✓ Time-travel debugging & undo/redo (keep past state snapshots)
// Immer (used by Redux Toolkit) lets you "mutate" a draft → produces an immutable result
produce(state, draft => { draft.items.push(item); }); // safe + readable
Immer 通过让你在一个 draft 上编写看起来像修改的代码来使嵌套的不可变更新变得符合人体工学,然后它将其转换为不可变更新。
不可变性是使基于引用的变化检测工作的机制 — 这就是为什么 [...items] 触发重新渲染但 items.push() 不会。
除了正确性,它还解锁了性能优化(memoization 比较引用)和强大的功能(撤销/重做、时间旅行)。
理解不可变更新模式(以及 Immer 之类的工具)对于正确使用 React/Redux 至关重要;修改 state 是最常见的初学者错误之一。