标准答案
- state 更新不是直接修改当前渲染里的变量,而是告诉 React 需要基于新的状态重新渲染组件。
- React 会把一次事件或一次调度范围内的多个更新合并处理,减少重复渲染。
- 函数组件中,当前 render 闭包里的 state 是本次渲染的快照,调用 setState 后这个快照不会立即改变。
- 需要基于上一次状态计算下一次状态时,应使用函数式更新,例如 setCount(prev => prev + 1)。
- 需要在状态更新后执行逻辑时,通常用 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 更新说成普通对象赋值,忽略批处理和渲染快照。