挂钩中 1 分钟计数器的重置无法正常工作
Reset of 1 minute counter in hooks isn't working properly
我正在创建 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>
);
}
有人可以帮我改进一下吗?谢谢
考虑让 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
更改时都会设置新的递归超时,这是不可取的;您将同时获得多个递归超时 运行。
如果我理解正确的话,问题是在每次更新时都会创建一个新的 setTimeout,并且所有创建的超时都会同时更新计数器。不要使用 setTimeout,而是尝试使用 setInterval,您可以在挂钩生命结束时清理它。
useEffect(() => {
let interval = setInterval(
() => setCounter(counter > 0 ? counter - 1 : counter),
1000
);
return () => clearInterval(interval);
}, [counter]);
我正在创建 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>
);
}
有人可以帮我改进一下吗?谢谢
考虑让 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
更改时都会设置新的递归超时,这是不可取的;您将同时获得多个递归超时 运行。
如果我理解正确的话,问题是在每次更新时都会创建一个新的 setTimeout,并且所有创建的超时都会同时更新计数器。不要使用 setTimeout,而是尝试使用 setInterval,您可以在挂钩生命结束时清理它。
useEffect(() => {
let interval = setInterval(
() => setCounter(counter > 0 ? counter - 1 : counter),
1000
);
return () => clearInterval(interval);
}, [counter]);