标准答案

  1. state 更新不是直接修改当前渲染里的变量,而是告诉 React 需要基于新的状态重新渲染组件。
  2. React 会把一次事件或一次调度范围内的多个更新合并处理,减少重复渲染。
  3. 函数组件中,当前 render 闭包里的 state 是本次渲染的快照,调用 setState 后这个快照不会立即改变。
  4. 需要基于上一次状态计算下一次状态时,应使用函数式更新,例如 setCount(prev => prev + 1)。
  5. 需要在状态更新后执行逻辑时,通常用 useEffect 观察状态变化,或把要使用的新值提前计算出来。

题目解析

“异步”不是指一定用 setTimeout,而是指更新会进入 React 的调度和批处理流程,不保证同步反映到当前变量。

React 18 的自动批处理范围更广,Promise、setTimeout、原生事件中的更新也可能被批处理。

理解 state 快照后,就能解释为什么连续 setCount(count + 1) 不一定累加多次,而 setCount(prev => prev + 1) 更可靠。

代码示例

下面的两段连续更新结果不同,关键在于是否基于上一次状态计算。

TSX
function Counter() {
  const [count, setCount] = useState(0)

  function addWrong() {
    setCount(count + 1)
    setCount(count + 1)
  }

  function addRight() {
    setCount(prev => prev + 1)
    setCount(prev => prev + 1)
  }

  return <button onClick={addRight}>{count}</button>
}

常见误区

  • 调用 setState 后马上读取当前 state,并认为它一定是新值。
  • 连续多次用 setCount(count + 1),却期待每次都基于最新状态累加。
  • 把 React state 更新说成普通对象赋值,忽略批处理和渲染快照。

作者信息