[英]setTimeout inside for loop in React component never stops iterating
I am trying to create a simple counter component in React.我正在尝试在 React 中创建一个简单的计数器组件。 It should start at 0, then iterate up to the passed in number.
它应该从 0 开始,然后迭代到传入的数字。 Here is the code I currently have:
这是我目前拥有的代码:
const Counter = ({ number }) => {
const [currentNumber, setCurrentNumber] = useState(0);
for (let i = 0; i < number; i++) {
setTimeout(() => setCurrentNumber(currentNumber + 1), 2000);
}
return <span>{currentNumber}</span>;
};
export default Counter;
What happens when I run this, is it basically keeps counting forever.当我运行它时会发生什么,它基本上一直在计数。
currentNumber
never stops incremementing, even once the number
has been reached. currentNumber
永远不会停止递增,即使达到该number
也是如此。
You should add currentNumber
as a dependency for useEffect()
.您应该添加
currentNumber
作为useEffect()
的依赖项。 This way useEffect()
will get triggered every second and a new timeout will be registered but only as long as currentNumber
is smaller than number
.这样
useEffect()
将每秒触发一次,并且将注册一个新的超时,但前提是currentNumber
小于number
。
const Counter = ({ number }) => { const [currentNumber, setCurrentNumber] = React.useState(0); React.useEffect(() => { if(currentNumber < number) setTimeout(() => setCurrentNumber(currentNumber + 1), 1000); }, [currentNumber]); return <span>{currentNumber}</span>; }; ReactDOM.render(<Counter number={20}/>, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <div id="root"></div>
Please try this code:请尝试以下代码:
const [currentNumber, setCurrentNumber] = useState(0);
useEffect(() => {
if (currentNumber >= number) return;
setTimeout(() => {
setCurrentNumber(currentNumber + 1);
}, 1000);
}, [currentNumber]);
return <span>{currentNumber}</span>;
I ran the code and it's getting stuck.我运行了代码,它卡住了。 Reason:
原因:
You're scheduling 5 timers which will all update currentNumber
to currentNumber + 1
.您正在安排 5 个计时器,它们都会将
currentNumber
更新为currentNumber + 1
。 currentNumber
is 0
, so it will update number
times to 1
after 2 seconds. currentNumber
为0
,因此它将在 2 秒后将number
次更新为1
。 You can approach this with an interval or a useEffect
:您可以使用间隔或
useEffect
来解决此问题:
useEffect(() => {
if (currentNumber < number)
setTimeout(() => setCurrentNumber(n => n + 1), 2000)
}, [number, currentNumber])
If you're using an interval, make sure you return a cleanup callback from useEffect
, like that:如果您使用间隔,请确保从
useEffect
返回清理回调,如下所示:
useEffect(() => {
const id = useInterval(...)
return () => clearInterval(id)
}, [...])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.