useState 到底怎么工作的?
聊聊状态是怎么被"记住"的
靠什么记住状态?
链表。React 在组件对应的 Fiber 节点上维护了一个 Hook 链表。
每次调用 useState,React 就在链表上移动指针,取出对应的值。
这也解释了为什么 Hook 不能在条件语句中调用:顺序必须一致,指针对不上。
更新队列
调用 setCount(c => c + 1) 时:
- 不会立即修改 state
- 创建一个更新对象,放入队列
- 下一次渲染时,遍历队列算出最新值
多次更新怎么算?
函数式写法
setCount(c => c + 1);
setCount(c => c + 1);
React 把两个 update 都放入队列,依次执行 +1, +1,最终结果是 +2。
直接传值
setCount(count + 1);
setCount(count + 1);
因为闭包,两次拿到的 count 都是旧值。队列里是 set(0+1), set(0+1),最终结果是 1。
注意事项
setState 用 Object.is 判断状态是否变化。
如果引用没变,React 会认为状态没变,跳过更新:
// ❌ 错误:引用没变
const obj = { name: 'John' };
setState(obj);
// ✅ 正确:返回新对象
setState({ ...obj });
总结
- 状态存在 Fiber 节点的 Hook 链表上
- 多次 setState 会放入队列,批量处理
- 闭包可能导致值不对,用函数式写法
- 必须返回新对象才能触发更新