React setState 批量更新机制

理解 React 中多次调用 setState 时的批量更新行为

问题

下面代码中,点击 “+3” 按钮后,age 的值是什么?

import { useState } from 'react';

export default function Counter() {
  const [age, setAge] = useState(42);
  function increment() {
    setAge(age + 1); 
  }
  return (
    <>
      <h1>Your age: {age}</h1>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
    </>
  );
}

解答

点击 “+3” 按钮后,age 的值是 43,而不是 45。

这是因为 setAge(age + 1) 使用的是当前渲染时的 age 值(42)。三次调用都是基于同一个值计算:

  • 第一次:setAge(42 + 1) → 43
  • 第二次:setAge(42 + 1) → 43
  • 第三次:setAge(42 + 1) → 43

React 会将这些更新合并,最终只触发一次重新渲染,结果为 43。

正确的做法是使用函数式更新:

function increment() {
  setAge(a => a + 1); // 基于上一次的状态值更新
}

这样每次调用都会基于最新的状态值计算:

  • 第一次:a => 42 + 1 → 43
  • 第二次:a => 43 + 1 → 44
  • 第三次:a => 44 + 1 → 45

关键点

  • setState 不会立即更新状态,而是在事件处理完成后批量处理
  • 多次调用 setState(value) 使用的是同一个快照值,会被合并
  • 使用函数式更新 setState(prev => newValue) 可以基于最新状态计算
  • 函数式更新确保每次更新都基于上一次的结果,适合连续更新场景