react-infinite-scroll-reverse
Version:
React infinite scroll reverse component
92 lines (83 loc) • 2.6 kB
JavaScript
import React, { useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";
function InfiniteScrollReverse({
className,
isLoading,
hasMore,
loadArea,
loadMore,
children
}) {
const infiniteRef = useRef();
const [currentPage, setCurrentPage] = useState(1);
const [scrollPosition, setScrollPosition] = useState(0); // Reset default page, if children equals to 0
useEffect(() => {
if (children.length === 0) {
setCurrentPage(1);
}
}, [children.length]);
useEffect(() => {
let {
current: scrollContainer
} = infiniteRef;
function onScroll() {
// Handle scroll direction
if (scrollContainer.scrollTop > scrollPosition) {// Scroll bottom
} else {
// Check load more scroll area
if (scrollContainer.scrollTop <= loadArea && !isLoading) {
// Check for available data
if (hasMore) {
// Run data fetching
const nextPage = currentPage + 1;
setCurrentPage(nextPage);
loadMore(nextPage);
}
}
} // Save event scroll position
setScrollPosition(scrollContainer.scrollTop);
}
scrollContainer.addEventListener("scroll", onScroll);
return () => {
scrollContainer.removeEventListener("scroll", onScroll);
};
}, [currentPage, hasMore, isLoading, loadArea, loadMore, scrollPosition]);
useEffect(() => {
let {
current: scrollContainer
} = infiniteRef;
if (children.length) {
// Get available top scroll
const availableScroll = scrollContainer.scrollHeight - scrollContainer.clientHeight; // Get motion for first page
if (currentPage === 1) {
// Move data to bottom for getting load more area
if (availableScroll >= 0) {
scrollContainer.scrollTop = availableScroll;
}
} else {
// Add scroll area for other pages
if (hasMore) {
scrollContainer.scrollTop = scrollContainer.clientHeight;
}
}
}
}, [children.length, currentPage, hasMore]);
return /*#__PURE__*/React.createElement("div", {
className: className,
ref: infiniteRef
}, children);
}
InfiniteScrollReverse.propTypes = {
className: PropTypes.string.isRequired,
children: PropTypes.array,
hasMore: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired,
loadMore: PropTypes.func.isRequired,
loadArea: PropTypes.number
};
InfiniteScrollReverse.defaultProps = {
className: "InfiniteScrollReverse",
children: [],
loadArea: 30
};
export default InfiniteScrollReverse;