简体   繁体   English

React 钩子 state 中的奇怪行为与 setInterval() 结合更新

[英]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挂钩,在功能组件的mountingupdating (取决于您的依赖数组)之后运行。

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 .现在,一旦您第一次更新countuseEffect将再次运行,因此由于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,更新一次计数 -> 使用fetchTimelineItemscount = 1 关闭,
Update count again -> Closure with fetchTimelineItems and count = 2,再次更新计数 -> 使用fetchTimelineItemscount = 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM