React中如何在满足特定条件时停止setInterval定时器
倒计时停止功能实现方案
现有代码核心问题
- 未存储定时器ID,无法调用
clearInterval主动终止定时器 - 未对倒计时归0的状态做判断,定时器会一直执行导致秒数变为负数
- 没有配置组件卸载时的定时器清理逻辑,会产生内存泄漏
- 未处理秒数归0后的分钟退位逻辑,倒计时到整分钟后运行逻辑错误
- 重复点击启动按钮会同时运行多个定时器,导致倒计时速度异常
具体实现步骤
- 新增
useRef存储定时器ID,不需要响应式更新的状态用useRef存储更高效,不会触发组件重渲染 - 启动定时器前先清空已存在的定时器,避免重复运行
- 在定时器的状态更新回调中增加归0判断,满足条件时直接清空定时器
- 补充秒数归0后的分钟退位逻辑
- 新增组件卸载时的清理逻辑,自动清空定时器
完整修正代码
import { useEffect, useState, useRef } from 'react'; // 组件内部逻辑 // 存储定时器ID,非响应式变量用useRef更合适 const timerRef = useRef<NodeJS.Timeout | null>(null); // 倒计时状态 const [timer, setTimer] = useState<{ minutes: number; seconds: number }>({ minutes: 0, seconds: 0 }); // 根据父组件传入props初始化倒计时 useEffect(() => { const check = rest.includes('Sec'); if (check) { let secs = parseFloat(rest.slice(0, 2)); // 用函数式更新不需要把timer加入依赖数组,避免不必要的重渲染 setTimer(() => ({ minutes: secs === 90 ? 1 : 0, seconds: secs === 90 ? 30 : secs })); } // 组件卸载时清空定时器,防止内存泄漏 return () => { if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; } } // 补充useEffect的依赖数组,把用到的外部变量rest加进来 }, [rest]); // 点击启动倒计时逻辑 const setTime = () => { // 启动前先清空已有的定时器,避免重复启动多个 if (timerRef.current) { clearInterval(timerRef.current); } timerRef.current = setInterval(() => { setTimer((prevState) => { // 已经归0,直接清空定时器 if (prevState.minutes === 0 && prevState.seconds === 0) { clearInterval(timerRef.current!); timerRef.current = null; return prevState; } // 秒数归0,分钟退位,秒数变成59 if (prevState.seconds === 0) { return { minutes: prevState.minutes - 1, seconds: 59 } } // 正常秒数减1 return { ...prevState, seconds: prevState.seconds - 1 } }) }, 1000); };
内容的提问来源于stack exchange,提问作者Richardson
相关产品推荐
相关产品推荐

