反应 useState,useEffect 没有按预期工作

React useState, useEffect not working as expected

我有一个用例,我想用 React hooks 解决它,但它没有像我预期的那样工作。

提前致谢。

这应该有效,你必须将 window.pageYOffsetisHeaderMoved 传递给 useEffect 以在每次更改时触发它,如果你离开它 []它会触发一次。

  useEffect(
    () => {
      window.addEventListener("scroll", handleScroll);
      return () => {
        window.removeEventListener("scroll", handleScroll);
      };
    },
    [isHeaderMoved]
  );

我想你也可以使用 useRef() 来做到这一点。

该组件添加一次事件监听器:仅在挂载时。那时,它会在那个特定的时间点添加 "captured" 的 handleScroll 侦听器和那个特定的 isHeaderMoved 值。每当页面滚动时,将调用的回调是具有初始 isHeaderMoved 值的回调。当前的代码基本上一遍又一遍地调用 handleScrollfalse

总之,需要对效果添加isHeaderMoved作为依赖。您还应该将 handleScroll 侦听器移动到效果中,以便 hooks eslint 插件可以更正确地跟踪它的依赖关系。

  useEffect(
    () => {
      const handleScroll = () => {
        if (window.pageYOffset > 0) {
          if (!isHeaderMoved) {
            setIsHeaderMoved(true)
          }
        } else if (isHeaderMoved) {
          setIsHeaderMoved(false)
        }
      }

      window.addEventListener("scroll", handleScroll)
      return () => {
        window.removeEventListener("scroll", handleScroll)
      }
    },
    [isHeaderMoved],
  )

请参阅 Dan Abromov 关于该主题的 post 中的这些部分(其中的示例比我能更好地解释它):

如果你有时间,值得通读整个post以充分理解事物。


根据 skyboxer 的评论,我想到这也可以,但我会保留以上所有内容以供参考。

  useEffect(() => {
    const handleScroll = () => {
      setIsHeaderMoved(window.pageYOffset > 0)
    }

    window.addEventListener("scroll", handleScroll)
    return () => {
      window.removeEventListener("scroll", handleScroll)
    }
  }, [])

我曾经遇到过同样烦人的问题

尝试在父代码中创建组件时在组件上添加一个 key prop

<yourcomponent key="some_unique_value" />

这是因为在大多数情况下,尤其是当您的组件被重用时,它通常可能仅在进行一些更改后重新呈现,而不是在您重用它时根据其创建方式实际再次创建它,因此 useEffect 不会被调用。例如在交换机、路由器、循环、条件...

因此添加密钥将防止这种情况发生。如果它在一个循环中,您需要确保每个元素都是唯一的,如果找不到更好的唯一键,可以在键中包含索引 i