Use this hook to watch element intersection
export const useIntersectionObserver = ({ root, target, onIntersect, threshold = 0.4, rootMargin = '0px', enabled = null }) => {
useEffect(() => {
if (!enabled) {
return;
}
const observer = new IntersectionObserver((entries) => entries.forEach((entry) => entry.isIntersecting && onIntersect()), {
root: root?.current,
rootMargin,
threshold,
});
const el = target?.current;
if (!el) {
return;
}
observer.observe(el);
return () => {
observer.unobserve(el);
};
}, [target?.current, enabled]);
};
Use above hook as below, in your page
const [currentPage, setPage] = useState(1);
const [endPage, setEndPage] = useState(false);
const [nextPageLoading, updatePageLoadingState] = useState(false);
const [localData, updateLocalData] = useState([]);
const { data: queryData, isLoading } = useDataQuery({ page: currentPage });
const [loadMoreRef, rootRef] = [useRef(null), useRef(null)];
useIntersectionObserver({
onIntersect: () => {
if (localData?.length >= 20 * currentPage && !nextPageLoading) {
setPage(currentPage + 1);
updatePageLoadingState(true);
setEndPage(false);
} else {
updatePageLoadingState(false);
setEndPage(true);
}
},
root: rootRef?.current,
target: loadMoreRef,
enabled: localData,
});
useEffect(() => {
const dedupedData = Array.from(
[...localData, ...(queryData || [])].reduce((m, t) => {
const removed = m?.filter((i) => i?.id !== t?.id);
return [...removed, t];
}, []),
);
updateLocalData(dedupedData);
updatePageLoadingState(false);
}, [queryData]);
Wrap the page with this component
<section ref={rootRef}>
// your code here
// loop through localData above here
//
</section>
Place this at the bottom of the page
{/* load more ref */}
<section ref={loadMoreRef} />
Example
<Fragment>
<section ref={rootRef}>
// your code here
// loop through localData above here
//
</section>
{/* load more ref */}
<section ref={loadMoreRef} />
</Fragment>