在React.js中添加滚动事件监听器后未收到回调

19

我按照这篇帖子在React.js中注册滚动事件的监听器来更新组件的样式的说明进行操作。

我有一个React组件,它从React-Bootstrap库https://react-bootstrap.github.io/中渲染出一个Table组件。

我认为我已正确地注册了事件监听器,但不确定为什么当我滚动表格时,我的handleScroll()回调函数没有被调用。是否因为事件监听器没有在实际的表格本身上注册?

感谢抽出时间阅读我的问题。欢迎提出任何反馈。

以下是我注册事件监听器的代码片段。

  handleScroll: function(event) {
    console.log('handleScroll invoked');
  },

  componentDidMount: function() {
    console.log('componentDidMount invoked');
    window.addEventListener('scroll', this.handleScroll);
  },

  componentWillUnmount: function() {
    console.log('componentWillUnmount invoked');
    window.removeEventListener('scroll', this.handleScroll);
  },

这是我的渲染函数的一小段代码。

  render: function() {

    var tableRows = this.renderTableRow(this.props.sheet);

    return (
      <Table striped bordered condensed hover>
        <TableHeaderContainer
          tableTemplateName={this.props.tableTemplateName}
          sheetName={this.props.sheet.name}/>
        <tbody>
          {tableRows}
        </tbody>
      </Table>
    );
  }
6个回答

31

你的代码看起来很好,所以可能不是窗口本身在滚动。表是否放置在 div 或其他具有 overflow: autooverflow:scroll 的元素内?如果是这样,侦听器必须附加到实际滚动的元素上,例如:

document.querySelector('.table-wrapper')
    .addEventListener('scroll', this.handleScroll);

如果是这种情况,那么在您的代码中为包装器添加一个React onScroll处理程序会更好。

<div onScroll={this.handleScroll}><Table....

2
你是正确的。我在错误的组件上注册了onscroll事件监听器。一旦我弄清楚了这一点,我就能够通过你上面列出的建议来注册我的回调函数了。 <code><div onScroll={this.handleScroll}...</code> - beyonddc

27

对我来说,唯一有效的方法是在 EventListener 的第三个参数中添加 true


componentDidMount() {
  window.addEventListener('scroll', this.handleScroll, true);
}

componentWillUnmount() {
  window.removeEventListener('scroll', this.handleScroll, true);
}

来源: https://github.com/facebook/react/issues/5042#issuecomment-145317519


这对我也起作用了。但是为什么呢? - undefined

2
使用钩子时,您可以像这样实现它。请注意,在组件不再挂载时删除事件侦听器非常重要。 useEffect 钩子中的 return 语句将在组件卸载时执行。
const handleScroll = () => {
  console.log('Scrolling...');
};

useEffect(() => {
  window.addEventListener('scroll', handleScroll, true);

  // Remove the event listener
  return () => {
    window.removeEventListener('scroll', handleScroll, true);
  };
}, []);

1

这篇文章有些老了,但是其中的答案启发了我解决问题的思路。我也有一个NextJS应用程序,并设置了以下CSS:

html, body {
    overflow-x: hidden;
}

body {
    position: relative;
}

这是为了防止任何元素在移动设备上创建水平侧边栏。然而,它会导致window.addEventListener(scroll)无法工作。最终对我有用的方法是: document.querySelector('body').addEventListener(scroll, handler)

希望这能帮助其他遇到类似情况的人。


0

我在Next.js应用程序中遇到了同样的问题。其中一个问题是我在根容器上放置了一个overflowX:hidden属性。在删除该属性并将以下代码放置在根组件中后,一切都正常工作。

请检查您放置此钩子的位置,并查看是否有任何溢出属性并将其删除。谢谢。

  const [show, setShow] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => {
      const scrollTotal =
        document.documentElement.scrollHeight -
        document.documentElement.clientHeight;
      if (document.documentElement.scrollTop / scrollTotal > 0.8) {
        setShow(true);
      } else {
        setShow(false);
      }
    };
    document.addEventListener("scroll", onScroll, true);
    return () => document.removeEventListener("scroll", onScroll, true);
  }, []);

0

谢谢dannyjolie - 这项工作

elementScrollData = (value) => {
  console.log('elementScrollData ', value);
} 
return (
      <div className="css-scroll-class" onScroll={elementScrollData}>
          Scroll element
      </div>
       );
}

1
请提供使用React Synthetic onScroll事件的工作代码链接 - 这会对我现在非常有帮助。 - MadHatter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接