使用useState和setInterval实现的React递增计时器异常如何修复
问题核心原因
- 闭包陷阱:useEffect的依赖数组仅包含
finished,定时器回调中捕获的currentTime永远是effect首次执行时的初始值,无法获取最新状态,导致判断逻辑失效。 - 状态直接修改:使用
currentTime.seconds++、currentTime.minutes++直接修改原状态对象,违反React状态不可变原则,会引发更新异常。 - 状态更新方式错误:新状态依赖前一次状态值时,未使用函数式更新写法,无法保证拿到最新的前序状态。
修复方案
修改useEffect逻辑,使用函数式更新获取最新的前序状态,不需要把currentTime加入依赖数组,同时调整进位判断逻辑避免秒数出现60的异常值:
useEffect(() => { let interval: NodeJS.Timeout | null = null; if (!finished) { interval = setInterval(() => { setCurrentTime(prevTime => { // 秒数到59直接进位,不会出现60的中间状态 if (prevTime.seconds === 59) { return { minutes: prevTime.minutes + 1, seconds: 0 }; } return { ...prevTime, seconds: prevTime.seconds + 1 }; }); }, 1000); } return () => { if (interval) clearInterval(interval); }; }, [finished]);
如果需要到达指定时长后自动停止,可以在状态更新前增加判断逻辑,当前时间等于目标时长时调用setFinished(true)即可。
内容的提问来源于stack exchange,提问作者dark09aura
相关产品推荐
相关产品推荐

