agentmentoragentmentor
Extension · 第 02 节:连续更新为什么会挤在同一个旧值上

为什么普通变量不行:一个反例

React 组件的重渲染由渲染调度器控制,不由 JavaScript 引擎自动触发。useState 返回一个 state 值和一个 setter;只有调用这个 setter,组件才会被标记为待重渲染,进入队列等待处理[^S2]。这条规则不管 setter 收到的是新值还是上一节里的 updater 函数,只要调用了它,重渲染就会被安排。

普通变量不经过这条通道。let count = 0 之后执行 count = count + 1,改变的只是这一次函数调用里、这一个变量绑定的值。JavaScript 引擎完成了赋值,但 React 不知道发生过这件事:赋值语句没有调用任何 React 提供的 API,也就不会触发前面说的排队机制。

结果是:内存里的 count 已经变了,屏幕上显示的还是上一次渲染时读到的旧值。JSX 里写的 {count} 只在组件函数被重新执行时才会重新求值,而组件函数只在 React 安排的重渲染发生时才会被重新执行。没有 setter 调用,就没有重渲染,屏幕停在原地。

JSX
function Counter() {
  let count = 0;
  function handleClick() {
    count = count + 1;
  }
  return <button onClick={handleClick}>{count}</button>;
}

点击这个按钮任意次数,屏幕上的数字都不会变。count 在内存里已经是点击次数,但组件函数没有被重新调用过,JSX 里的 {count} 还是第一次渲染时读到的 0。

This is example content demonstrating what the tool can generate. Not counted toward progress.