React中useEffect与setInterval异常行为及清理函数作用解析
React StrictMode下useEffect与setInterval的异常分析与解决方案
问题场景
在React应用中使用useEffect结合setInterval时出现异常:
- 不添加清理函数时,
count每次递增2而非预期的1 - 添加清理函数
return () => { clearInterval(id); };后,count恢复正常每次递增1 - 移除
index.js中的<React.StrictMode>,即使没有清理函数也能正常运行
对应的代码片段:
import React, { useState, useEffect } from "react"; function Timer() { const [count, setCount] = useState(0); useEffect(() => { const id = setInterval(() => { setCount((prevCount) => prevCount + 1); }, 1000); // 取消注释下方清理函数后,功能正常 // return () => { // clearInterval(id); // }; }, []); return ( <div className="Timer"> <h2>Timer Two</h2> <h3>{count}</h3> </div> ); } export default Timer;
原因解析
<React.StrictMode>的作用
StrictMode是React仅在开发环境生效的工具,核心目的是提前揪出代码里潜在的副作用问题。它会刻意重复执行以下操作:
- 组件构造函数、
useState初始化函数、useReducer更新函数 useEffect和useLayoutEffect的回调函数及其清理函数
这种重复执行是为了暴露那些没正确处理清理逻辑的副作用,比如未销毁的定时器、订阅等,避免上线后出现内存泄漏或异常行为。
无清理函数时的异常原因
当没有清理函数时,StrictMode的双重执行会导致:
- 第一次执行
useEffect,创建定时器A,每1秒触发一次setCount - StrictMode触发第二次
useEffect执行,又创建定时器B,同样每1秒触发一次setCount - 两个定时器并行运行,每1秒各自调用一次
setCount,所以count每次会被加2
清理函数解决问题的原理
添加return () => { clearInterval(id); };后,StrictMode的执行流程变成了:
- 第一次执行
useEffect,创建定时器A - StrictMode准备第二次执行
useEffect前,会先调用第一次useEffect返回的清理函数,清除定时器A - 第二次执行
useEffect,创建定时器B - 此时页面上只有定时器B在运行,每1秒触发一次
setCount,count自然每次递增1
另外,清理函数还有个关键作用:当组件卸载时,会自动执行清理逻辑清除定时器,避免内存泄漏——这也是React副作用管理的最佳实践,不管有没有StrictMode都应该加上。
内容的提问来源于stack exchange,提问作者omar
相关产品推荐
相关产品推荐

