【问题标题】:Strange behavior in React hook state updates in combination with setInterval()与 setInterval() 结合使用 React 钩子状态更新中的奇怪行为
【发布时间】:2021-08-06 20:32:30
【问题描述】:

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

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

查看代码框链接以重现此行为。

预期的行为是在 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

【问题讨论】:

  • 您正在设置多个超时。使用效果在安装时运行

标签: reactjs react-hooks setinterval


【解决方案1】:

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

因此,只要您更新 count,它就会一直运行。

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

现在,最后,您创建的每个Interval 都会在其中创建一个称为closure 的东西。在这个closure 里面有一个fetchTimelineItems 函数,沿着那个时间点count 的值。

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

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

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

【讨论】:

    猜你喜欢
    • 2019-04-01
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    相关资源
    最近更新 更多