setInterval 中的 setState 未按预期工作。知道为什么吗?

setState inside setInterval not working as expected. Any Idea why?

我想每 2 秒更新一次状态并渲染一些图像 这绝对没问题

useEffect(() => {
    setTimeout(() => {
      if (workImages.currentIndex > workImages.items.length - 2) {
        setWorkImages({ ...workImages, currentIndex: 0 });
      } else {
        setWorkImages({
          ...workImages,
          currentIndex: ++workImages.currentIndex,
        });
      }
    }, 2000);
  }, [workImages]);

这仅适用于其他情况

useEffect(() => {
    setInterval(() => {
      if (workImages.currentIndex > workImages.items.length - 2) {
        setWorkImages({ ...workImages, currentIndex: 0 });
      } else {
        setWorkImages({
          ...workImages,
          currentIndex: ++workImages.currentIndex,
        });
      }
    }, 2000);
  }, []);

谁能解释为什么?

第一个有效,因为您在 依赖项数组中包含了 workImages 数组:只要 workImages 发生变化,钩子就会触发。

你的第二个例子有一个空的依赖数组,这意味着它会在组件安装时触发一次,但不会在 workImages.currentIndex 更改时重新触发。

第一个示例 有效,因为它监听 workImages。因此,每次 workImages 更改时,您都可以使用 setWorkImages 设置新图像。

第二个示例 仅在加载页面时触发 ONCE

有关 useEffect 的更多信息,请查看此处:https://reactjs.org/docs/hooks-effect.html

假设 workImages.currentIndex 从 1 开始。

在第一个示例中,第一次调用函数时,useEffect 得到设置,2 秒后 setTimeout 触发。这会将状态更新为 workImages.currentIndex 现在是 2,这会触发重新渲染。现在 workImages 已经改变,因为它是 useEffect 的依赖项,该函数被再次调用,两秒后另一个超时 运行s.

现在在第二个例子中,第一次调用函数时发生了非常相似的事情,但第二次调用时 useEffect 不会再 运行 了。不依赖 workImages.

现在,您可能认为这无关紧要,因为您使用的是 setInterval 而不是 setTimeout,而且您几乎是正确的。

2 秒后,间隔触发,您传递给它的函数再次 运行s。

但是关闭了来自第一个workImages变量函数 运行 的时间,而不是第二次。 workImages.currentIndex 的值(就该函数而言)仍然是 1,因为它还没有从状态中获得更新的值。所以它再次将其设置为 2。这不是更改(它已经是 2,所以您不会重新渲染。2 秒后它再次将其设置为 2,并且一直如此。