You need to enable JavaScript to run this app. ReactJS stale closure问题:快速点击时setTimeout调用hooks仅触发2次重渲染
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS stale closure问题:快速点击时setTimeout调用hooks仅触发2次重渲染

问题核心原因

1. 过时闭包捕获了旧状态

你快速多次点击按钮时,所有触发的onClosure函数都来自val = 0的初始渲染上下文,每个onClosure中注册的setTimeout回调捕获的val永远是初始值0,不会随后续状态更新变化。

2. 所有状态更新请求值相同

1000ms后所有定时器回调依次执行时:

  • 每个回调里的console.log语句打印的都是捕获到的旧值0,所以你点击多少次就会输出多少组before = 0、inside = 0的日志,对应你观测到的「setTimeout内部语句均被正常执行」的现象。
  • 每个回调执行setVal(val + 1)等价于setVal(0 + 1),也就是所有的状态更新请求都是把val设置为1。

3. React状态更新的跳过逻辑

  • 页面加载时已经完成一次初始渲染,打印outside = 0。
  • 第一个定时器回调执行时,React检测到val从0变为1,触发一次重渲染,打印outside = 1。
  • 后续所有定时器回调执行setVal(1)时,当前的val已经是1,状态没有发生变更,React会直接跳过重渲染,不会产生新的outside日志。
  • 算上初始渲染,你总共只会观测到2次渲染日志,也就是你说的「仅触发2次重渲染」的现象。

修复方案

如果要实现点击N次最终val变为N的效果,把状态更新改为函数式写法即可,函数式更新可以拿到最新的状态值,不受过时闭包影响:

setVal(prev => prev + 1)

内容的提问来源于stack exchange,提问作者GyuMin Han

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 04:48:03