如何使反应倒数计时器

use*_*410 3 javascript countdown reactjs react-hooks

我正在尝试用反应做倒数计时器。基本上是从 10 到 0 倒计时,当 0 时我会调用一些函数。

我为我找到了一些理想的例子:https : //codesandbox.io/s/0q453m77nw?from-embed 但它是一个类组件,我不想用功能组件和钩子来做,但我不能。

我试过:

function App() {
  const [seconds, setSeconds] = useState(10);
  useEffect(() => {
    setSeconds(setInterval(seconds, 1000));
  }, []);

  useEffect(() => {
    tick();
  });

  function tick() {
    if (seconds > 0) {
      setSeconds(seconds - 1)
    } else {
      clearInterval(seconds);
    }
  }

  return (

    <div className="App">
      <div
        {seconds}
      </div>
    </div>
  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

它从 10 倒数到 0 非常快,而不是在 10 秒内。我错在哪里?

Bre*_*ody 11

看起来多个useEffect钩子导致倒计时每秒运行一次以上。

这里有一个简单的解决方案,我们检查secondsuseEffect钩之一:

  • 用于在 1 秒后setTimeout更新seconds,或
  • 做其他事情(倒计时结束时要调用的函数)

这种方法有一些缺点,见下文。

function App() {
  const [seconds, setSeconds] = React.useState(10);

  React.useEffect(() => {
    if (seconds > 0) {
      setTimeout(() => setSeconds(seconds - 1), 1000);
    } else {
      setSeconds('BOOOOM!');
    }
  });

  return (
    <div className="App">
      <div>
        {seconds}
      </div>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'))
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

缺点

使用setInterval的缺点是它可能会被停止 - 例如,组件被卸载,您导航到不同的选项卡,或关闭您的计算机。如果计时器需要更高的鲁棒性,更好的选择是将 an 存储endTime在状态中(如全局存储或上下文),并让您的组件根据 来检查当前时间endTime以计算倒计时。