Обнаружение, когда пользователь прокручивает дно div с помощью React js
У меня есть сайт с разными разделами. Я использую segment.io для отслеживания различных действий на странице. Как определить, прокручивается ли пользователь в нижней части div? Я пробовал следующее, но, похоже, это срабатывает, как только я просматриваю страницу, а не когда
Я добрался до нижней части 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);
}
};
Ответы
Ответ 1
Вы можете использовать el.getBoundingClientRect().bottom
чтобы проверить, было ли просмотрено дно.
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);
}
};
Ответ 2
Еще более простой способ сделать это с помощью scrollHeight, scrollTop и clientHeight.
Вычтите высоту прокрутки из общей высоты прокрутки. Если это равно видимой области, вы достигли дна!
element.scrollHeight - element.scrollTop === element.clientHeight
Чтобы реагировать, просто добавьте прослушиватель onScroll к элементу прокрутки и используйте event.target
в обратном вызове.
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>
);
}
}
Я обнаружил, что это более интуитивно понятно, потому что он имеет дело с самим прокручиваемым элементом, а не с window
, и он следует обычному способу действий React (не используя идентификаторы, игнорируя узлы DOM).
Вы также можете манипулировать уравнением, чтобы запускать страницу вверх (например, ленивая загрузка контента/бесконечная прокрутка).
Ответ 3
Мы также можем определить конец прокрутки div с помощью ссылки.
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);
Ответ 4
Я знаю, что на этот вопрос уже дан ответ, но, думаю, еще одно хорошее решение - это использовать то, что уже доступно в сообществе открытого исходного кода, вместо DIY. React Waypoints - это библиотека, которая существует для решения этой самой проблемы. (Хотя не спрашивайте меня, почему эта проблемная область определения того, прокручивает ли человек элемент HTML, называется "путевые точки", ха-ха)
Я думаю, что он очень хорошо спроектирован с контрактом на реквизит и определенно рекомендую вам проверить его.
Ответ 5
Расширяя ответ chandresh, чтобы использовать ответные хуки и реф, я бы сделал это так;
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>
);
}
Ответ 6
Добавьте следующие функции в свой React.Component, и все готово:]
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
);
}