web-dev-qa-db-fra.com

Détecter quand l’utilisateur fait défiler jusqu’au bas de la div avec React js

J'ai un site web avec différentes sections. J'utilise segment.io pour suivre différentes actions sur la page. Comment puis-je détecter si un utilisateur a défilé jusqu'au bas d'un div? J'ai essayé ce qui suit, mais cela semble se déclencher dès que je fais défiler la page et non pas lorsque j'ai atteint le bas de la div.

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

vous pouvez utiliser el.getBoundingClientRect().bottom pour vérifier si le fond a été visualisé

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

Une méthode encore plus simple consiste à utiliser scrollHeight , scrollTop et clientHeight .

Soustrayez la hauteur de défilement de la hauteur totale de défilement. Si cela est égal à la zone visible, vous avez atteint le bas!

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

Dans react, ajoutez simplement un écouteur onScroll à l'élément scrollable et utilisez event.target dans le rappel.

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

J’ai trouvé cela plus intuitif car il s’agissait de l’élément de défilement lui-même, et non du window, et il suivait la manière normale React de faire les choses (ne pas utiliser les identifiants, ignorer Nœuds DOM).

Vous pouvez également manipuler l'équation pour déclencher plus haut dans la page (chargement paresseux de contenu/défilement infini, par exemple).

44
Brendan McGill

Nous pouvons également détecter la fin du défilement de div en utilisant 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);
6
Chandresh

Ajoutez les fonctions suivantes dans votre React.Component et vous avez terminé:]

  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

Je sais que l'on a déjà répondu à cette question, mais je pense qu'une autre bonne solution consiste à utiliser ce qui est déjà disponible dans la communauté open source au lieu du bricolage. React Waypoints est une bibliothèque qui existe pour résoudre ce problème même. (Bien que ne me demandez pas pourquoi cet espace de problème permettant de déterminer si une personne défile devant un élément HTML s'appelle "waypoints", haha)

Je pense qu’il est très bien conçu avec son contrat d’accessoires et je vous encourage vivement à le vérifier.

0
Danchez

Étendre la réponse de Chandresh à l’utilisation des crochets de réaction et de référence je le ferais comme ceci;

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
Allan Guwatudde