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

React StrictMode下SetInterval为何触发双渲染?(含useEffect清理)

React StrictMode下定时器导致重复渲染的问题解析

场景复现

我们有一个简易计数器组件,在useEffect中创建定时器更新状态,同时在清理函数中清除定时器。当组件被包裹在StrictMode中时,控制台每3秒会批量打印两次RE_RENDERING;移除StrictMode后则每3秒正常打印一次。

组件代码

Counter组件:

const Counter = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setCount((old) => old + 1);
    }, 3000);
    return () => clearInterval(id);
  }, []);

  console.log("RE_RENDERING");
  return <div>{count}</div>;
};

App组件:

export default function App() {
  return (
    <StrictMode>
      <Counter />
    </StrictMode>
  );
}

React官方明确说明:

React总会在下一次渲染的Effect执行前清理上一次渲染的Effect。

问题原因解析

很多人会误以为StrictMode的双执行只针对初始挂载,但实际上在开发环境下,StrictMode会让所有组件渲染(包括初始渲染和状态更新触发的重渲染)都执行两次,目的是提前暴露潜在的副作用问题(比如未正确清理的定时器、订阅等)。

具体执行流程:

  1. 初始挂载阶段

    • 第一次渲染组件:打印RE_RENDERING
    • 执行第一个useEffect,创建定时器A
    • React立即调用第一个useEffect的清理函数,清除定时器A(模拟组件卸载后重新挂载的场景)
    • 第二次渲染组件:打印RE_RENDERING
    • 执行第二个useEffect,创建定时器B(这个定时器会被保留)
  2. 3秒后定时器触发阶段

    • 定时器B调用setCount更新状态,触发组件重渲染
    • 由于StrictMode的机制,这次重渲染会执行两次,因此控制台会批量打印两次RE_RENDERING
    • 后续每3秒定时器触发状态更新,都会重复这个双渲染的过程

关键结论

  • StrictMode的双渲染覆盖所有渲染场景,不止初始挂载
  • 你的清理逻辑是有效的:第一次创建的定时器A确实被清理了,最终只有定时器B在运行
  • 每3秒的两次log是状态更新触发的双渲染导致的,而非多个定时器同时运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:53:12