19

I followed the instruction from this post Update style of a component onScroll in React.js to register event listener for scroll event.

I have a React component that renders a Table component from the React-Bootstrap library https://react-bootstrap.github.io/

I think I registered the event listener correctly but I am not sure why when I scroll down the table, my handleScroll() callback is not getting invoked. Is it because the event listener is not registered on the actual table itself?

Thanks for taking your time reading my question. Any feedback is appreciated.

Here's a snippet of how I register for the event listener.

  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);
  },

Here's a snippet of my render function.

  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>
    );
  }
Community
  • 1
  • 1
beyonddc
  • 1,246
  • 3
  • 13
  • 26

6 Answers6

31

Your code looks good, so it's probably not the window itself that is scrolling. Is the table placed inside a div or something that has overflow: auto or overflow:scroll? If so, the listener must be attached to the actual element that is scrolling, e.g.

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

If this is the case, then just adding a React onScroll handler to the wrapper in your code would be better

<div onScroll={this.handleScroll}><Table....
dannyjolie
  • 10,959
  • 3
  • 33
  • 28
  • 2
    You were correct. I was registering the onscroll event listener on the wrong component. Once I got that straighten out, I was able to register my call back via the suggestion you listed above.
    – beyonddc Mar 30 '16 at 18:36
24

For me the only thing that worked was adding true to the third argument in the EventListener:


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

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

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

carkod
  • 1,844
  • 19
  • 32
2

When using hooks you can implement it like this. Please note that it's important to remove the event listener when the component is no longer mounted.

The return statement in useEffect hook will execute when the component unmounts.

const handleScroll = () => {
  console.log('Scrolling...');
};

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

  // Remove the event listener
  return () => {
    window.removeEventListener('scroll', handleScroll, true);
  };
}, []);
DileepNimantha
  • 215
  • 2
  • 14
1

This is pretty old, but the accepted answer inspired my solution to my problem. I also have a NextJS app and I set the following CSS:

html, body {
    overflow-x: hidden;
}

body {
    position: relative;
}

This is to prevent any elements from creating horizontal sidebars primarily for mobile devices. However, it causes window.addEventListener(scroll) to not work. What ended up working for me was to do: document.querySelector('body').addEventListener(scroll, handler).

Hope this helps anyone else in a similar situation.

Designly
  • 266
  • 1
  • 9
0

Thank you dannyjolie - this work

elementScrollData = (value) => {
  console.log('elementScrollData ', value);
} 
return (
      <div className="css-scroll-class" onScroll={elementScrollData}>
          Scroll element
      </div>
       );
}
Yanov
  • 655
  • 7
  • 13
  • 1
    Please provide a link to working code using React Synthetic `onScroll` event--it would help me greatly right now. – MadHatter Aug 21 '20 at 02:16
0

I was having the same issue in Next.js App. One of the issues was that I had placed on the root container an overflowX:hidden property. After removing that and placing the below code in the root component, everything worked well.

Check where you are placing this hook and see if there are any overflow properties and remove them. Thanks.

  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);
  }, []);
briancoder
  • 159
  • 1
  • 9