开发环境React重挂载组件:为何UI仅显单组件快照且setInterval执行两次?
问题解答
核心问题出在React开发环境的严格模式上——它是React专门用来提前排查潜在bug的机制,默认会在开发环境下重复执行组件的挂载逻辑(包括useEffect这类副作用代码)。
为什么setInterval跑两次,但UI看起来正常?
如果你的useEffect没写清理定时器的逻辑,就会出现这种矛盾:
- 第一次挂载:执行
useEffect创建了定时器A,开始触发count递增。 - 严格模式会模拟“挂载-卸载-重新挂载”的流程,但第一次的定时器A没被清除,重新挂载时又创建了定时器B,两个定时器同时在跑。
- 但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
相关产品推荐
相关产品推荐

