[英]Strange behavior in React hook state updates in combination with setInterval()
The below code correctly updates the count state, but when outputting the count value with console.log, it is showing very strange behavior if called from a function within an setInterval inside useEffect() hook.下面的代码正确更新了计数 state,但是当使用 console.log 输出计数值时,如果从 useEffect() 钩子内的 setInterval 中的 function 调用,它会显示非常奇怪的行为。
You would expect to see an incremental number in the console.log but the output from the fetchTimelineItems() function is bizar.您可能希望在 console.log 中看到一个递增的数字,但 fetchTimelineItems() function 中的 output 很奇怪。 When the count is 1, the output alternates between 0 and 1. When the count is 2 or more it outputs all the numbers in random order.当计数为 1 时,output 在 0 和 1 之间交替。当计数为 2 或更多时,它以随机顺序输出所有数字。
See codesandbox link to reproduce this behavior.请参阅代码和框链接以重现此行为。
The expected behavior is to see the correct count value in the fetchTimelineItems() function.预期的行为是在 fetchTimelineItems() function 中看到正确的计数值。
Thanks in advance for pointing me in the right direction to get this fixed.提前感谢您为我指出正确的方向以解决此问题。
const Example = ({ title }) => {
const [count, setCount] = useState(0);
const handleCount = () => {
setCount(count + 1);
console.log(count);
};
function fetchTimelineItems() {
console.log("count from within fetch function: " + count);
}
useEffect(() => {
setInterval(() => {
fetchTimelineItems();
}, 3000)
},[count]);
return (
<div>
<p>{title}</p>
<button onClick={handleCount}>Increase count</button>
</div>
);
};
https://codesandbox.io/s/count-update-s5z94?file=/src/index.js https://codesandbox.io/s/count-update-s5z94?file=/src/index.js
The useEffect
hooks, runs after mounting
and updating
(depending on your dependency array) of your functional component. useEffect
挂钩,在功能组件的mounting
和updating
(取决于您的依赖数组)之后运行。
So, it keeps running whenever you update your count
.因此,只要您更新count
,它就会一直运行。
Now, once you update count
for the first time, the useEffect
will again run, thus creating a new Interval
because of setInterval
.现在,一旦您第一次更新count
, useEffect
将再次运行,因此由于setInterval
创建了一个新的Interval
。 This is why you have multiple output statement.这就是为什么您有多个 output 语句的原因。
Now, finally, each Interval
you create is creating what is called a closure
inside it.现在,最后,您创建的每个Interval
都在其中创建所谓的closure
。 Inside this closure
there is the fetchTimelineItems
function along the value of count
at that point of time.在这个closure
中,沿着那个时间点的count
数值有fetchTimelineItems
function。
So, for every update of count
you are creating new intervals like this.因此,对于count
的每次更新,您都会像这样创建新的间隔。
Mount -> Closure with fetchTimelineItems
and count
= 0, Mount -> Closure with fetchTimelineItems
and count
= 0,
Update count once -> Closure with fetchTimelineItems
and count
= 1,更新一次计数 -> 使用fetchTimelineItems
和count
= 1 关闭,
Update count again -> Closure with fetchTimelineItems
and count
= 2,再次更新计数 -> 使用fetchTimelineItems
和count
= 2 关闭,
This is why you have all the values printing in the console.这就是您在控制台中打印所有值的原因。 Why it is printing old values is because that's how closures
work in javascript.为什么要打印旧值是因为这就是 javascript 中closures
的工作方式。 They remember the values at the time of their creation.他们记得他们创建时的价值观。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.