我正在尝试建立一个倒计时器,但我面临着一个我不理解的问题。当我按下start时,计时器工作正常,当我暂停计时器时,也是如此。
问题是当我按下reset按钮时,该按钮应该停止倒计时并将其重置为其原始值(此时为25)。
当我按下它时,倒计时停止,它转到25,然后它转到前一个数字。例如,如果我在16点按它,它会停止,转到25,然后回到16或15。
我猜这与useEffect有关,因为handleReset同时更新了counter和runnning,但我不太确定原因。如果有人能给我解释一下原因,那就太好了。
这是App.js
const App = () => {
const [counter, setCounter] = useState(25);
const [running, setRunning] = useState(false);
const handlePlayPause = () => {
running ? setRunning(false) : setRunning(true);
};
const handleReset = () => {
setRunning(false);
setCounter(25);
};
useEffect(() => {
if (running) {
counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
}
}, [counter, running]);
return (
<div className="container">
<h1>Pomodoro Timer</h1>
<div className="set-timer">
<Break />
<Session />
</div>
<Display counter={counter} />
<Controller handlePlayPause={handlePlayPause} handleReset={handleReset} />
</div>
);
};完整的代码在这里:https://codepen.io/mugg84/pen/yLepaKm?editors=0010
谢谢你的帮忙!
发布于 2020-07-03 00:06:06
这里有一些我可能会改变的地方。
首先,handleReset可能不应该将running设置为false,因为计数器仍在运行。您只需重置该值。
然后,为了解决这些问题,我建议您使用setInterval,您需要将clearInterval与useRef结合使用。逻辑可以简化,但我想这更具可读性。
const handleReset = () => {
// stop on reset
clearInterval(timer.current)
timer.current = undefined;
setCounter(25);
};
const timer = React.useRef(undefined);
React.useEffect(() => {
if (running) {
if (!timer.current) {
timer.current = setInterval(() => setCounter(prevCounter => prevCounter - 1), 1000);
} else if(counter == 0 && timer.current) {
// stop if reached 0
clearInterval(timer.current)
timer.current = undefined;
}
} else {
// stop if turned off
clearInterval(timer.current)
timer.current = undefined;
}
}, [counter, running]);发布于 2020-07-02 23:45:54
您可以执行以下更改。问题是由于计数器设置状态在1秒后,此时running已设置为false,因此当计数器在1秒后更新时,它将变为旧值。因此,我们可以将其设置为null,并处理explicitly.Below代码按您所描述的那样工作的情况
const App = () => {
const [counter, setCounter] = React.useState(25);
const [running, setRunning] = React.useState(false);
const handlePlayPause = () => {
running ? setRunning(false) : setRunning(true);
};
const handleReset = () => {
setRunning(null);
setCounter(25);
};
React.useEffect(() => {
if (running) {
counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
}
else if(running == null){
setCounter(25);
}
}, [counter, running]);
return (
<div className="container">
<h1>Pomodoro Timer</h1>
<div className="set-timer">
<Break />
<Session />
</div>
<Display counter={counter} />
<Controller handleReset={handleReset} handlePlayPause={handlePlayPause}/>
</div>
);
};发布于 2020-07-02 23:45:54
我没有使用clearTimeout,这是导致问题的原因。
我已经更新了useEffect,它工作得很棒。
useEffect(() => {
if (running && counter > 0) {
const timer = setTimeout(() => setCounter(counter - 1), 1000);
return () => clearTimeout(timer);
}
}, [counter, running]);https://stackoverflow.com/questions/62699436
复制相似问题