Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应倒计时重置_Javascript_Reactjs_Settimeout_Use Effect - Fatal编程技术网

Javascript 反应倒计时重置

Javascript 反应倒计时重置,javascript,reactjs,settimeout,use-effect,Javascript,Reactjs,Settimeout,Use Effect,我试图建立一个倒计时计时器,但我面临一个问题,我不明白。 当我按下“开始”时,计时器工作正常,当我暂停计时器时,计时器工作正常 问题是当我按下重置按钮时,该按钮应该停止倒计时并将其重置为原始值(此时为25) 当我按下它时,倒计时停止,它变为25,但随后变为上一个数字。例如,如果我在16点按它,它会停止,变为25,然后在16或15点返回 我想这与useffect有关,因为handleReset同时更新计数器和运行,但我不确定原因。 如果有人能向我解释一下原因那就太好了 下面是App.js cons

我试图建立一个倒计时计时器,但我面临一个问题,我不明白。 当我按下“开始”时,计时器工作正常,当我暂停计时器时,计时器工作正常

问题是当我按下重置按钮时,该按钮应该停止倒计时并将其重置为原始值(此时为25)

当我按下它时,倒计时停止,它变为25,但随后变为上一个数字。例如,如果我在16点按它,它会停止,变为25,然后在16或15点返回

我想这与
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