You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么useEffect依赖数组内多个状态同时变更时仅执行一次?

React 连续触发多个setState时useEffect仅执行一次的底层逻辑

复现代码

点击交互逻辑:

<div
  onClick={() => {
    setTest1((x: number) => x + 1);
    setTest2((x: number) => x + 3); 
  }}
>
  one? two?
</div>

状态与副作用定义:

const [test1, setTest1] = useState(1);
const [test2, setTest2] = useState(1);
useEffect(() => {
  console.log('!@#$');
  console.log(test1, test2);
}, [test1, test2]);

现象说明

触发div的点击事件时,test1、test2的状态更新方法被连续调用,但控制台仅打印一次!@#$,绑定的useEffect回调仅执行一次。

底层实现逻辑

  • 状态更新批处理机制:React从设计层面就不会在每次setState被调用时立刻触发组件重渲染,会先把同一个执行上下文中触发的所有状态更新收集到待更新队列。React 18版本之前,仅React合成事件(比如示例中的onClick)、组件生命周期函数内的更新会被自动批处理;18版本之后全场景默认开启批处理,哪怕是setTimeout、Promise回调、原生DOM事件内的连续setState调用,都会被纳入合并范围。
  • 单轮渲染合并所有状态变更:等当前同步任务执行完毕,React才会统一消费待更新队列里攒下的所有状态变更,计算出组件的最终状态值,仅触发一次组件render函数执行、一次DOM差异更新与提交,不会因为调用了两次setState就重复走两遍完整渲染流程。
  • useEffect的执行规则:useEffect的回调触发时机是组件完成DOM提交、页面更新落地之后,此时React会统一遍历所有注册的effect,对比当前依赖值和上一轮渲染的缓存值是否存在差异。由于两次setState的更新结果是在同一轮渲染中提交的,依赖对比流程仅会执行一次,检测到test1、test2的值均发生变化后,也只会触发一次对应的effect回调,不会拆分执行两次。

内容的提问来源于stack exchange,提问作者이재현

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 09:18:27