首页 > 解决方案 > 挂钩中 1 分钟计数器的重置无法正常工作

问题描述

我正在创建 1 分钟计数器并且它正在工作,但是当我单击重置按钮重新启动同一个计数器时,会出现奇怪的行为。

这是代码

export default function App() {
  const [counter, setCounter] = useState(60);
  useEffect(() => {
    counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
  }, [counter]);
  const handleReset = () => {
    setCounter(60);
  }
  return (
    <div className="App">
      <h1>Counter</h1>
      <p>{counter}</p>
      <button onClick={handleReset}>Reset</button>
    </div>
  );
}

沙盒中的代码

有人可以帮我改进吗?谢谢

标签: javascriptreactjstimeout

解决方案


考虑useEffect使用一个空的依赖数组和一个间隔而不是超时。然后,在超时回调中,counter如果大于 0,则递减:

const App = () => {
  const [counter, setCounter] = React.useState(60);
  React.useEffect(() => {
    setInterval(() => {
      // Must use callback form here; outer `counter` is in stale closure
      setCounter(counter => counter === 0 ? counter : counter - 1);
    }, 1000);
  }, []);
  const handleReset = () => {
    setCounter(60);
  }
  return (
    <div className="App">
      <h1>Counter</h1>
      <p>{counter}</p>
      <button onClick={handleReset}>Reset</button>
    </div>
  );
}
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class="react"></div>

您当前使用[counter]依赖数组的实现意味着每次counter更改时都会设置一个新的递归超时,这是不可取的;您将同时运行多个递归超时。


推荐阅读