javascript - React 应用程序没有按预期触发 onScroll 事件

标签 javascript reactjs browser react-hooks vertical-scrolling

我试图显示一个特定的组件 - 当显示它的页面从顶部滚动 X 个点时,它是一个“粘性标题”部分。

我尝试使用 useWindowScroll 执行此操作钩子(Hook) use-react包,以及下面的一个简短片段:

  const [scrollTop, setScrollTop] = useState(0);

  function setScroll() {
    console.log('setScroll');
    setScrollTop(window.pageYOffset);
    console.log(new Date().getTime());
  }

  useEffect(() => {
    function watchScroll() {
      console.log('watchScroll');
      window.addEventListener("scroll", setScroll);
    }
    watchScroll();
    return () => {
      window.removeEventListener("scroll", setScroll);
    };
  });

  console.log('scroll top:', scrollTop);

理想情况下,我们可能希望在处理每个新的滚动事件之前有一点延迟,但这不是我的问题。

我希望setScroll每当我滚动时,每隔几毫秒就会被调用。然而,这并没有发生。事实上,我从未见过它被调用过。

由于它没有在适当的时候被调用,我的const shouldShowStickyHeader = scrollTop > 1000;始终设置为 false 。因此,我的从未显示过。我希望它在滚动到顶部距离为 1,000 时出现。

问题是什么?

我还尝试了效果 Hook 内所有内容的版本:

  const [scrollTop, setScrollTop] = useState(0);

  useEffect(() => {
    function setScroll() {
      console.log('setScroll');
      setScrollTop(window.pageYOffset);
      console.log(new Date().getTime());
    }
    window.addEventListener("scroll", setScroll);
    return () => {
      window.removeEventListener("scroll", setScroll);
    };
  }, [scrollTop]);

我没看到setScroll正在控制台中打印。可能是什么问题?

我用 document.querySelectorAll("*").forEach(element => element.addEventListener("scroll", ({target}) => console.log(target, target?.id, target?.parent, target?.parent?.id))); 做了一个小测试。当我滚动时确实会触发一些事件。请参阅:

<div data-testid="vdp-scroll-container" id="vdp-scroll-container" class="jsx-1959376998 vdp-scroll-container">
...
<div data-testid="vdp-scroll-container" id="vdp-scroll-container" class="jsx-1959376998 vdp-scroll-container">

我尝试将列表直接放在这个元素上:

document.getElementById('#vdp-scroll-container')?.addEventListener("scroll", setScroll);
    return () => {
      document.getElementById('#vdp-scroll-container')?.removeEventListener("scroll", setScroll);
    };

不过,我没有看到任何东西被解雇。

<div/> 上的样式如下:

height: 100%;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow-y: scroll;

因此我什么也得不到吗?

最佳答案

您应该将一个空数组传递给 useEffect 作为第二个参数,以便仅在组件第一次安装后才触发该函数。不传递第二个参数,将在每次重新渲染后触发该函数,传递 [scrollTop] 将在每次 scrollTop 更改时触发该函数。

这样的事情应该有效:

  const [offset, setOffset] = React.useState(null);
  const setScroll = () => {
    setOffset(window.scrollY);
  };

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

工作示例:https://codesandbox.io/s/zen-cdn-ll6es?file=/src/App.js

关于javascript - React 应用程序没有按预期触发 onScroll 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68944015/

相关文章:

javascript - 为什么传递函数引用失败而使用函数声明却失败?

javascript - 如何在确保完成先前功能的情况下以固定间隔调用功能

javascript - Angular 4 : setValue formBuilder empty array

javascript - React-Native 标签栏 : Remove horizontal line (React Native UI Kitten + React Navigation)

javascript - 在数组中查找对象?

javascript - 在提示时检测空值

javascript - 在嵌套组件中更新状态的正确方法

java - Selenium 2 : Store webdriver instance id of open window to create new webdriver instance with this id

css - 在 Windows 7 中禁用表单字段样式

Selenium : handling popups