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

Strange behavior in React hook state updates in combination with setInterval()

下面的代码正确地更新了计数状态,但是当使用 console.log 输出计数值时,如果从 useEffect() 钩子内的 setInterval 中的函数调用它会显示出非常奇怪的行为。

您可能希望在 console.log 中看到递增的数字,但 fetchTimelineItems() 函数的输出很奇怪。当计数为 1 时,输出在 0 和 1 之间交替。当计数为 2 或更多时,它以随机顺序输出所有数字。

请参阅 codesandbox link 以重现此行为。

预期的行为是在 fetchTimelineItems() 函数中看到正确的计数值。

预先感谢您指出正确的方向来解决此问题。

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

函数组件的 useEffect 钩子,在 mountingupdating 之后 运行(取决于您的依赖项数组)。

因此,每当您更新 count 时,它都会保持 运行ning。

现在,一旦您第一次更新 countuseEffect 将再次 运行,从而创建一个新的 Interval 因为 setInterval .这就是为什么你有多个输出语句。

现在,最后,您创建的每个 Interval 都在其中创建了所谓的 closure。在这个 closure 里面有 fetchTimelineItems 函数沿着 count 在那个时间点的值。

因此,对于 count 的每次更新,您都在创建这样的新间隔。

挂载 -> fetchTimelineItemscount = 0 时关闭,
更新计数一次 -> fetchTimelineItemscount = 1 时关闭,
再次更新计数 -> 使用 fetchTimelineItemscount = 2,

关闭

这就是您在控制台中打印所有值的原因。 为什么打印旧值是因为 closures 在 javascript 中就是这样工作的。他们记得创建时的价值观。