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

开发环境React重挂载组件:为何UI仅显单组件快照且setInterval执行两次?

问题解答

核心问题出在React开发环境的严格模式上——它是React专门用来提前排查潜在bug的机制,默认会在开发环境下重复执行组件的挂载逻辑(包括useEffect这类副作用代码)。

为什么setInterval跑两次,但UI看起来正常?

如果你的useEffect没写清理定时器的逻辑,就会出现这种矛盾:

  1. 第一次挂载:执行useEffect创建了定时器A,开始触发count递增。
  2. 严格模式会模拟“挂载-卸载-重新挂载”的流程,但第一次的定时器A没被清除,重新挂载时又创建了定时器B,两个定时器同时在跑。
  3. 但UI没出现每次加2的情况,是因为React的状态更新依赖当前渲染周期的状态快照。比如当前count是0,两个定时器的回调在同一个时间点触发,读取的都是0这个快照值,执行setCount(0+1)后,最终状态只会变成1,而非2。所以你看起来UI只更了一次,但实际上两个定时器都在运行。

怎么确认?

给定时器回调加个console.log,你会发现每个间隔时间里,日志会打印两次,但UI数字只加1。等下一个间隔,两个定时器又会同时触发,读取的count是1,最终状态变成2,以此类推。

解决办法

在useEffect里返回清理函数,卸载组件时清除定时器,同时推荐用函数式更新来避免状态快照的问题:

useEffect(() => {
  const timer = setInterval(() => {
    setCount(prevCount => prevCount + 1);
  }, 1000);
  return () => clearInterval(timer);
}, []);

这样严格模式下,第一次挂载的定时器会在卸载时被清掉,重新挂载只会创建一个新定时器,就不会有重复运行的问题了。

内容的提问来源于stack exchange,提问作者Harsh Rathore

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:25:23