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

如何在React中正确使用setTimeout?解决连续点击按钮仅执行一次状态更新的问题

问题原因分析

这个问题的核心是闭包导致的旧状态引用,再结合React状态更新的特性共同造成的:

  • 当你连续点击两次按钮时,click函数会立刻触发两次setTimeout,这两个setTimeout里的click2函数都会捕获到点击瞬间的numbers状态(也就是初始的{a:10, b:30, c:100, d: ...}对象)。
  • 2秒后两个click2依次执行,但它们都是基于同一个旧的numbers对象来计算新状态,第二次更新会直接覆盖第一次的结果,所以最终看起来只完成了一次状态更新。

简单来说,两次更新都用了同一个“过期”的状态值,没有基于最新的状态进行计算。

修复方法:使用函数式状态更新

React的useState返回的状态更新函数支持传入一个更新函数,而不是直接传入新的状态值。这个更新函数会接收当前最新的状态作为参数,返回新的状态对象。这样每次更新都会基于最新的状态计算,就不会出现覆盖的问题了。

修改后的代码如下:

const Button = () => { 
  const [numbers, setNumbers] = useState({ a: 10, b: 30, c: 100, d: new Date() }); 
  const click = () => { 
    setTimeout(click2, 2000); 
  }; 
  const click2 = () => { 
    // 改用函数式更新,prevNumbers是当前最新的状态
    setNumbers(prevNumbers => ({ 
      a: prevNumbers.a + 1, 
      b: prevNumbers.b + 1, 
      c: prevNumbers.c + 1, 
      d: new Date() 
    })); 
  }; 
  return ( 
    <> 
      <button onClick={click}>+</button> 
      <p>{numbers.a}</p> 
      <p>{numbers.b}</p> 
      <p>{numbers.c}</p> 
      <p>{numbers.d.toLocaleString()}</p> 
    </> 
  ); 
};

这样修改后,不管你连续点击多少次按钮,每个click2都会基于当时最新的状态来更新,最终状态会累积每次点击的增量。

内容的提问来源于stack exchange,提问作者Батрадз Санакоев

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:57:48