Javascript 反应倒计时重置
我试图建立一个倒计时计时器,但我面临一个问题,我不明白。 当我按下“开始”时,计时器工作正常,当我暂停计时器时,计时器工作正常 问题是当我按下重置按钮时,该按钮应该停止倒计时并将其重置为原始值(此时为25) 当我按下它时,倒计时停止,它变为25,但随后变为上一个数字。例如,如果我在16点按它,它会停止,变为25,然后在16或15点返回 我想这与Javascript 反应倒计时重置,javascript,reactjs,settimeout,use-effect,Javascript,Reactjs,Settimeout,Use Effect,我试图建立一个倒计时计时器,但我面临一个问题,我不明白。 当我按下“开始”时,计时器工作正常,当我暂停计时器时,计时器工作正常 问题是当我按下重置按钮时,该按钮应该停止倒计时并将其重置为原始值(此时为25) 当我按下它时,倒计时停止,它变为25,但随后变为上一个数字。例如,如果我在16点按它,它会停止,变为25,然后在16或15点返回 我想这与useffect有关,因为handleReset同时更新计数器和运行,但我不确定原因。 如果有人能向我解释一下原因那就太好了 下面是App.js cons
useffect
有关,因为handleReset
同时更新计数器和运行
,但我不确定原因。
如果有人能向我解释一下原因那就太好了
下面是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>
);
};
const-App=()=>{
常数[计数器,设置计数器]=使用状态(25);
const[running,setRunning]=useState(false);
常量handlePlayPause=()=>{
正在运行?设置正在运行(false):设置正在运行(true);
};
常量handleReset=()=>{
setRunning(假);
设置计数器(25);
};
useffect(()=>{
如果(正在运行){
计数器>0&&setTimeout(()=>setCounter(计数器-1),1000);
}
},[计数器,运行];
返回(
波莫多罗计时器
);
};
完整代码如下:
谢谢你的帮助 您可以执行以下更改。问题是由于计数器设置状态在1秒后出现,此时running已设置为false,因此当CONINTER在1秒后更新时,它将变为旧值。所以,我们可以将其设置为null并显式处理该情况
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>
);
};
const-App=()=>{
常量[计数器,设置计数器]=React.useState(25);
const[running,setRunning]=React.useState(false);
常量handlePlayPause=()=>{
正在运行?设置正在运行(false):设置正在运行(true);
};
常量handleReset=()=>{
setRunning(空);
设置计数器(25);
};
React.useffect(()=>{
如果(正在运行){
计数器>0&&setTimeout(()=>setCounter(计数器-1),1000);
}
else if(running==null){
设置计数器(25);
}
},[计数器,运行];
返回(
波莫多罗计时器
);
};
我没有使用clearTimeout
,这就是问题的原因
我已经更新了useffect
,它的效果非常好
useEffect(() => {
if (running && counter > 0) {
const timer = setTimeout(() => setCounter(counter - 1), 1000);
return () => clearTimeout(timer);
}
}, [counter, running]);
这里的一些事情我可能会改变
首先,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]);
setTimeout(()=>setCounter(计数器-1),1000)代码>导致问题。在重置计数器之前,需要停止setTimeout
。