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

React的useState setter回调会多次执行吗?计数异常问题求解

问题根因

这个现象是React 18+开发环境下严格模式(StrictMode)的特性导致的,和你猜想的Fiber架构设计相关,但不是console被重写隐藏日志这么离谱的设计,具体逻辑如下:

  1. React 18之后,开发环境下如果项目用了<StrictMode>包裹根组件,所有传递给状态更新函数(比如你这里的setList)的回调会被故意执行两次,目的是提前暴露非幂等的状态更新逻辑问题,帮你提前排查生产环境可能出现的bug。
  2. 为了避免两次执行的日志刷屏干扰调试,React开发环境会临时屏蔽第二次执行状态更新回调时的所有console输出,所以你看不到第二次++counter的执行日志,只会发现counter的数值莫名其妙跳了2。
  3. 你的counter是模块级别的全局可变变量,在状态更新回调里执行++counter属于在更新逻辑中引入了外部副作用,本身就是非幂等操作:第一次执行回调counter加1,生成的列表比如X1,X2会被React直接丢弃;第二次隐式执行时counter已经是2,再加1就变成3,最终返回的列表是X1,X3,这才是React实际用来更新状态的值,所以控制台打印的第一次执行的列表和实际渲染结果不一致。
  4. 你把++counter移到setList回调外部后运行正常的原因是:严格模式只会重复执行状态更新回调,不会重复执行整个onClick事件处理函数,所以counter每次点击只会加1,更新回调里读取到的就是正确的数值。

验证方法

你可以找到项目入口文件,把包裹App组件的<StrictMode>标签去掉,再运行代码点击按钮,结果就会完全符合你的预期。另外这个重复执行的逻辑只会出现在开发环境,生产环境打包后不会有这个问题。

内容的提问来源于stack exchange,提问作者0x24a537r9

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 23:54:04