Detecteren wanneer gebruiker naar de onderkant van de div scrolt met React js

Ik heb een website met verschillende secties. Ik gebruik segment.io om verschillende acties op de pagina bij te houden. Hoe kan ik detecteren of een gebruiker naar de onderkant van een div heeft gescrolld? Ik heb het volgende geprobeerd, maar het lijkt te worden geactiveerd zodra ik op de pagina scrol en niet wanneer:
Ik heb de onderkant van de div bereikt.

componentDidMount() {
  document.addEventListener('scroll', this.trackScrolling);
}
trackScrolling = () => {
  const wrappedElement = document.getElementById('header');
  if (wrappedElement.scrollHeight - wrappedElement.scrollTop === wrappedElement.clientHeight) {
    console.log('header bottom reached');
    document.removeEventListener('scroll', this.trackScrolling);
  }
};

Antwoord 1, autoriteit 100%

Een nog eenvoudigere manier om dit te doen is met scrollHeight, scrollTopen clientHeight.

Trek de verschuifbare hoogte af van de totale verschuifbare hoogte. Als dit gelijk is aan het zichtbare gebied, heb je de bodem bereikt!

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

Als reactie, voeg gewoon een onScroll-luisteraar toe aan het schuifbare element en gebruik event.targetin de 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>
    );
  }
}

Ik vond dit intuïtiever omdat het het schuifbare element zelf behandelt, niet het window, en het volgt de normale React-manier om dingen te doen (geen id’s gebruiken, DOM-knooppunten negerend).

Je kunt de vergelijking ook manipuleren om hoger op de pagina te activeren (bijvoorbeeld lui laden van inhoud/oneindig scrollen).


Antwoord 2, autoriteit 55%

u kunt el.getBoundingClientRect().bottomgebruiken om te controleren of de onderkant is bekeken

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

Antwoord 3, autoriteit 16%

Hier is een oplossing met behulp van React Hooks en ES6:

import React, { useRef, useEffect } from 'react';
const MyListComponent = () => {
  const listInnerRef = useRef();
  const onScroll = () => {
    if (listInnerRef.current) {
      const { scrollTop, scrollHeight, clientHeight } = listInnerRef.current;
      if (scrollTop + clientHeight === scrollHeight) {
        // TO SOMETHING HERE
        console.log('Reached bottom')
      }
    }
  };
  return (
    <div className="list">
      <div className="list-inner" onScroll={() => onScroll()} ref={listInnerRef}>
        {/* List items */}
      </div>
    </div>
  );
};
export default List;

Antwoord 4, autoriteit 7%

We kunnen ook het scroll-einde van div detecteren met ref.

import React, { Component } from 'react';
import {withRouter} from 'react-router-dom';
import styles from 'style.scss';
class Gallery extends Component{ 
  paneDidMount = (node) => {    
    if(node) {      
      node.addEventListener("scroll", this.handleScroll.bind(this));      
    }
  }
  handleScroll = (event) => {    
    var node = event.target;
    const bottom = node.scrollHeight - node.scrollTop === node.clientHeight;
    if (bottom) {      
      console.log("BOTTOM REACHED:",bottom); 
    }    
  }
  render() {
    var that = this;        
    return(<div className={styles.gallery}>
      <div ref={that.paneDidMount} className={styles.galleryContainer}>
        ...
      </div>
    </div>);   
  }
}
export default withRouter(Gallery);

Antwoord 5, autoriteit 5%

Dit antwoord is van Brendan, laten we het functioneel maken

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

Als de eerste div niet scrollbaar is, zal deze niet werken en onScroll werkte niet voor mij in een onderliggend element zoals div na de eerste div, dus onScroll zou bij de eerste HTML-tag moeten staan ​​die een overloop heeft


Antwoord 6, autoriteit 4%

Het antwoord van chandresh uitbreiden om react hooks te gebruiken en ref, ik zou het zo doen;

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

Antwoord 7, autoriteit 3%

Voeg de volgende functies toe aan je React.Component en je bent klaar:]

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

Antwoord 8, autoriteit 2%

Ik weet dat dit al is beantwoord, maar ik denk dat een andere goede oplossing is om te gebruiken wat al beschikbaar is in de open source-gemeenschap in plaats van doe-het-zelf. React Waypointsis een bibliotheek die bestaat om dit probleem op te lossen. (Vraag me echter niet waarom deze probleemruimte om te bepalen of een persoon voorbij een HTML-element scrolt “waypoints” wordt genoemd, haha)

Ik vind het erg goed ontworpen met zijn rekwisietencontract en raad je zeker aan om het eens te proberen.


Antwoord 9

Ik heb follow in mijn code gebruikt

.modify-table-wrap {
  opvulling-top: 50px;
  hoogte: 100%;
  overloop-y: scroll;
}

En code toevoegen 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>
            )

Antwoord 10

Om te beoordelen of mijn browser naar de onderkant van een div heeft gescrolld, heb ik deze oplossing gekozen:

const el = document.querySelector('.your-element');
const atBottom = Math.ceil(el.scrollTop + el.offsetHeight) === el.scrollHeight;

Antwoord 11

Zet een div met 0 hoogte achter je scrollende div. gebruik vervolgens deze aangepaste hooksom te detecteren of deze div zichtbaar is.

 const bottomRef = useRef();
  const reachedBottom = useCustomHooks(bottomRef);
  return(
  <div>
   {search resault}
  </div>
  <div ref={bottomRef}/> )

reachedBottomschakelt naar trueals je de bodem bereikt

Other episodes