我在ReactJs中实现秒表,这是我的代码现在的样子:
const App: React.FC = () => {
const [seconds, setSeconds] = useState(0);
const [isPaused, setIsPaused] = useState(false);
const secondsToTimerFormat = (seconds: number): string => {
console.log(seconds)
return (seconds-seconds%60)/60+":"+seconds%60
}
const manipulateTimer = (toPauseTimer: boolean) => {
setIsPaused(toPauseTimer);
}
useEffect(() => {
if(!isPaused){
setTimeout(() => {
setSeconds(seconds + 1)
}, 1000)
}
}, [seconds, isPaused])
return (
<div className="App">
{secondsToTimerFormat(seconds)}
<div>
<button onClick={() => {manipulateTimer(true)}}>Pause</button>
<button onClick={() => {manipulateTimer(false)}}>Resume</button>
<button onClick={() => {
setSeconds(0);
}}>Reset</button>
</div>
</div>
);
}
我希望它能正常工作。但是“Reset”按钮没有正常工作。如果我在13秒后点击“Reset”,这就是console.log()
的输出。
如果我在useEffect()
中添加一个新变量,例如let execute: boolean = true
,然后在useEffect()
清理中将其设置为false
,则一切都按预期工作。
所以,我知道修复,但我想知道当前行为背后的原因。我知道当我点击重置时,已经有一个useEffect()
运行,秒值为13
。但由于它的setTimeout()
在一秒内结束,同时,我正在执行setSeconds(0)
,为什么以前的useEffect()
在停止前会运行多次?
2条答案
按热度按时间v6ylcynt1#
尝试使用
setInterval
和单独的方法来处理计时器状态:Link到沙箱
fae0ux8s2#
像这样的问题通常是因为正在使用的计时器在渲染之间没有被清除。另外,当下一个状态依赖于当前状态时,最好使用第二种形式的状态设置器函数,它将当前状态作为参数并返回下一个状态。修改useEffect如下所示,以使其工作: