如何清理useEffect外的函数?React定时器内存泄漏修复
解决React组件卸载后定时器导致的状态更新警告
问题根源是组件卸载后,setInterval和setTimeout仍在执行,尝试更新已卸载组件的状态,触发内存泄漏警告。要解决这个问题,你需要用useRef存储定时器ID,再通过useEffect的清理函数在组件卸载时清除定时器,同时处理重复点击的情况。
具体修改步骤:
- 添加定时器引用:新增两个
useRef来保存定时器ID,方便后续清理:
const time = useRef(30); const intervalRef = useRef(null); const timeoutRef = useRef(null);
- 修改
disableResendBtn函数:将定时器ID存入ref,同时每次点击前先清除之前的定时器(避免重复触发):
function disableResendBtn() { // 先清除之前未完成的定时器 if (intervalRef.current) clearInterval(intervalRef.current); if (timeoutRef.current) clearTimeout(timeoutRef.current); time.current = 30; setsendCodeBtnDisabled(true); setsendCodeBtnText(`${i18n.t('RESEND')}(${time.current})`); intervalRef.current = setInterval(() => { time.current -= 1; setsendCodeBtnText(`${i18n.t('RESEND')}(${time.current})`); console.log(time.current); }, 1000); timeoutRef.current = setTimeout(() => { setsendCodeBtnDisabled(false); setsendCodeBtnText(i18n.t('RESEND')); clearInterval(intervalRef.current); // 清理引用 intervalRef.current = null; timeoutRef.current = null; }, 30000); }
- 添加
useEffect清理函数:监听组件卸载事件,清除所有未完成的定时器:
useEffect(() => { return () => { if (intervalRef.current) clearInterval(intervalRef.current); if (timeoutRef.current) clearTimeout(timeoutRef.current); }; }, []);
关键说明:
- 用
useRef存储定时器ID是因为ref的.current属性在组件生命周期内保持不变,能在useEffect的清理函数中访问到。 - 每次点击按钮前清除旧定时器,防止多次点击导致多个定时器同时运行,造成状态混乱。
- 组件卸载时,
useEffect的返回函数会自动执行,清除所有未完成的异步任务,避免状态更新到已卸载的组件上。
内容的提问来源于stack exchange,提问作者Jess
相关产品推荐
相关产品推荐

