useState 到底怎么工作的?

聊聊状态是怎么被"记住"的

靠什么记住状态?

链表。React 在组件对应的 Fiber 节点上维护了一个 Hook 链表。

每次调用 useState,React 就在链表上移动指针,取出对应的值。

这也解释了为什么 Hook 不能在条件语句中调用:顺序必须一致,指针对不上。

更新队列

调用 setCount(c => c + 1) 时:

  1. 不会立即修改 state
  2. 创建一个更新对象,放入队列
  3. 下一次渲染时,遍历队列算出最新值

多次更新怎么算?

函数式写法

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

注意事项

setStateObject.is 判断状态是否变化。

如果引用没变,React 会认为状态没变,跳过更新

// ❌ 错误:引用没变
const obj = { name: 'John' };
setState(obj);

// ✅ 正确:返回新对象
setState({ ...obj });

总结

  • 状态存在 Fiber 节点的 Hook 链表上
  • 多次 setState 会放入队列,批量处理
  • 闭包可能导致值不对,用函数式写法
  • 必须返回新对象才能触发更新