Detecting when user scrolls to bottom of div with React js

后端 未结 9 2159
悲哀的现实
悲哀的现实 2020-11-28 21:17

I have a website with different sections. I am using segment.io to track different actions on the page. How can I detect if a user has scrolled to the bottom of a div? I hav

相关标签:
9条回答
  • 2020-11-28 21:38

    This answer belongs to Brendan but in functional components

    export default () => {
       const handleScroll = (e) => {
           const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
           if (bottom) { 
               console.log("bottom")
           }
        }
    
    return (
         <div onScroll={handleScroll}  style={{overflowY: 'scroll', maxHeight: '400px'}}  >
            //overflowing elements here
       </div>
     );
     }
    

    If the first div is not scrollable it won't work and onScroll didn't work for me in a child element like div after the first div so onScroll should be at the first HTML tag that has an overflow

    0 讨论(0)
  • 2020-11-28 21:40

    you can use el.getBoundingClientRect().bottom to check if the bottom has been viewed

    isBottom(el) {
      return el.getBoundingClientRect().bottom <= window.innerHeight;
    }
    
    componentDidMount() {
      document.addEventListener('scroll', this.trackScrolling);
    }
    
    componentWillUnmount() {
      document.removeEventListener('scroll', this.trackScrolling);
    }
    
    trackScrolling = () => {
      const wrappedElement = document.getElementById('header');
      if (this.isBottom(wrappedElement)) {
        console.log('header bottom reached');
        document.removeEventListener('scroll', this.trackScrolling);
      }
    };
    
    0 讨论(0)
  • 2020-11-28 21:44

    Add following functions in your React.Component and you're done :]

      componentDidMount() {
        window.addEventListener("scroll", this.onScroll, false);
      }
    
      componentWillUnmount() {
        window.removeEventListener("scroll", this.onScroll, false);
      }
    
      onScroll = () => {
        if (this.hasReachedBottom()) {
          this.props.onScrollToBottom();
        }
      };
    
      hasReachedBottom() {
        return (
          document.body.offsetHeight + document.body.scrollTop ===
          document.body.scrollHeight
        );
      }
    
    0 讨论(0)
  • 2020-11-28 21:49

    An even simpler way to do it is with scrollHeight, scrollTop, and clientHeight.

    Subtract the scrolled height from the total scrollable height. If this is equal to the visible area, you've reached the bottom!

    element.scrollHeight - element.scrollTop === element.clientHeight
    

    In react, just add an onScroll listener to the scrollable element, and use event.target in the callback.

    class Scrollable extends Component {
    
      handleScroll = (e) => {
        const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
        if (bottom) { ... }
      }
    
      render() {
        return (
          <ScrollableElement onScroll={this.handleScroll}>
            <OverflowingContent />
          </ScrollableElement>
        );
      }
    }
    

    I found this to be more intuitive because it deals with the scrollable element itself, not the window, and it follows the normal React way of doing things (not using ids, ignoring DOM nodes).

    You can also manipulate the equation to trigger higher up the page (lazy loading content/infinite scroll, for example).

    0 讨论(0)
  • 2020-11-28 21:52

    Extending chandresh's answer to use react hooks and ref I would do it like this;

    import React, {useState, useEffect} from 'react';
    
    export default function Scrollable() {
        const [referenceNode, setReferenceNode] = useState();
        const [listItems] = useState(Array.from(Array(30).keys(), (n) => n + 1));
    
        useEffect(() => {
            return () => referenceNode.removeEventListener('scroll', handleScroll);
        }, []);
    
        function handleScroll(event) {
            var node = event.target;
            const bottom = node.scrollHeight - node.scrollTop === node.clientHeight;
            if (bottom) {
                console.log('BOTTOM REACHED:', bottom);
            }
        }
    
        const paneDidMount = (node) => {
            if (node) {
                node.addEventListener('scroll', handleScroll);
                setReferenceNode(node);
            }
        };
    
        return (
            <div
                ref={paneDidMount}
                style={{overflowY: 'scroll', maxHeight: '400px'}}
            >
                <ul>
                    {listItems.map((listItem) => <li>List Item {listItem}</li>)}
                </ul>
            </div>
        );
    }
    
    0 讨论(0)
  • 2020-11-28 21:59

    I used follow in my code

    .modify-table-wrap {
        padding-top: 50px;
        height: 100%;
        overflow-y: scroll;
    }
    
    

    And add code in target js

        handleScroll = (event) => {
            const { limit, offset } = this.state
            const target = event.target
            if (target.scrollHeight - target.scrollTop === target.clientHeight) {
                this.setState({ offset: offset + limit }, this.fetchAPI)
            }
        }
        return (
                <div className="modify-table-wrap" onScroll={this.handleScroll}>
                   ...
                <div>
                )
    
    
    0 讨论(0)
提交回复
热议问题