React Native定时器结束后onTimerFinish函数未触发问题求助
问题原因及修复方案
核心问题:闭包陷阱导致无法获取最新时间差
你的代码里,useEffect的依赖数组是空的,这意味着里面的setInterval回调只会捕获组件初始渲染时的timeBetween值,后续currentTime更新时,回调里的timeBetween不会跟着变化,自然无法正确判断倒计时是否结束。另外,你在回调里先检查timeBetween再更新currentTime,逻辑顺序也反了,而且没做防重复触发的处理。
修复后的完整代码
import { useState, useEffect } from 'react'; const MyCountdownTimer = (props) => { const targetTime = new Date(props.targetDate).getTime(); const [currentTime, setCurrentTime] = useState(Date.now()); // 计算实时时间差 const timeBetween = targetTime - currentTime; const days = Math.floor(timeBetween / (1000 * 60 * 60 * 24)); const hours = Math.floor((timeBetween % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((timeBetween % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((timeBetween % (1000 * 60)) / 1000); useEffect(() => { // 先判断初始状态是否已经超时 if (timeBetween < 0) { props.onTimerFinish(); return; } const interval = setInterval(() => { const newCurrentTime = Date.now(); const newTimeBetween = targetTime - newCurrentTime; // 更新当前时间 setCurrentTime(newCurrentTime); // 检查是否超时,且只触发一次 if (newTimeBetween < 0) { props.onTimerFinish(); clearInterval(interval); // 触发后立即清除定时器 } }, 1000); return () => clearInterval(interval); }, [props.targetDate, props.onTimerFinish]); // 加入依赖,确保回调能获取最新的props和时间相关值 // UI渲染部分,根据需求用View包裹展示即可 return ( <div> <span>{days}天</span> <span>{hours}时</span> <span>{minutes}分</span> <span>{seconds}秒</span> </div> ); }; export default MyCountdownTimer;
关键修复点说明
- 解决闭包问题:在
setInterval回调里直接计算最新的newTimeBetween,不依赖外部的timeBetween变量;同时给useEffect添加正确的依赖项,确保组件能响应props变化。 - 逻辑顺序调整:先更新
currentTime,再判断时间差是否小于0,保证判断的是最新状态。 - 防重复触发:触发
onTimerFinish后立即清除定时器,避免重复调用回调。 - 初始状态检查:组件挂载时先判断是否已经超时,避免错过触发时机。
内容的提问来源于stack exchange,提问作者Chaudhry Talha
相关产品推荐
相关产品推荐

