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会让所有组件渲染(包括初始渲染和状态更新触发的重渲染)都执行两次,目的是提前暴露潜在的副作用问题(比如未正确清理的定时器、订阅等)。
具体执行流程:
初始挂载阶段
- 第一次渲染组件:打印
RE_RENDERING - 执行第一个
useEffect,创建定时器A - React立即调用第一个
useEffect的清理函数,清除定时器A(模拟组件卸载后重新挂载的场景) - 第二次渲染组件:打印
RE_RENDERING - 执行第二个
useEffect,创建定时器B(这个定时器会被保留)
- 第一次渲染组件:打印
3秒后定时器触发阶段
- 定时器B调用
setCount更新状态,触发组件重渲染 - 由于StrictMode的机制,这次重渲染会执行两次,因此控制台会批量打印两次
RE_RENDERING - 后续每3秒定时器触发状态更新,都会重复这个双渲染的过程
- 定时器B调用
关键结论
- StrictMode的双渲染覆盖所有渲染场景,不止初始挂载
- 你的清理逻辑是有效的:第一次创建的定时器A确实被清理了,最终只有定时器B在运行
- 每3秒的两次log是状态更新触发的双渲染导致的,而非多个定时器同时运行
内容的提问来源于stack exchange,提问作者glo
相关产品推荐
相关产品推荐

