首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React Countdown重置

React Countdown重置
EN

Stack Overflow用户
提问于 2020-07-02 23:05:58
回答 3查看 321关注 0票数 0

我正在尝试建立一个倒计时器,但我面临着一个我不理解的问题。当我按下start时,计时器工作正常,当我暂停计时器时,也是如此。

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

当我按下它时,倒计时停止,它转到25,然后它转到前一个数字。例如,如果我在16点按它,它会停止,转到25,然后回到16或15。

我猜这与useEffect有关,因为handleReset同时更新了counterrunnning,但我不太确定原因。如果有人能给我解释一下原因,那就太好了。

这是App.js

代码语言:javascript
复制
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

谢谢你的帮忙!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-03 00:06:06

这里有一些我可能会改变的地方。

首先,handleReset可能不应该将running设置为false,因为计数器仍在运行。您只需重置该值。

然后,为了解决这些问题,我建议您使用setInterval,您需要将clearIntervaluseRef结合使用。逻辑可以简化,但我想这更具可读性。

代码语言:javascript
复制
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]);
票数 1
EN

Stack Overflow用户

发布于 2020-07-02 23:45:54

您可以执行以下更改。问题是由于计数器设置状态在1秒后,此时running已设置为false,因此当计数器在1秒后更新时,它将变为旧值。因此,我们可以将其设置为null,并处理explicitly.Below代码按您所描述的那样工作的情况

代码语言:javascript
复制
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>
  );
};
票数 0
EN

Stack Overflow用户

发布于 2020-07-02 23:45:54

我没有使用clearTimeout,这是导致问题的原因。

我已经更新了useEffect,它工作得很棒。

代码语言:javascript
复制
useEffect(() => {
    if (running && counter > 0) {
      const timer = setTimeout(() => setCounter(counter - 1), 1000);
      return () => clearTimeout(timer);
    }
  }, [counter, running]);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62699436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档