{{#if framework == "nextjs"}} "use client"; {{/if}} import { useEffect, useRef, useState } from "react"; {{#if framework == "nextjs"}} import { useRouter, useSearchParams } from "next/navigation"; {{else}} import { useNavigate, useSearchParams } from "react-router"; {{/if}} import { formUrlQuery } from "@/lib/utils/url-helpers"; const LoadMore = ({ hasNextPage }: { hasNextPage: boolean }) => { {{#if framework == "nextjs"}} const router = useRouter(); const searchParams = useSearchParams(); {{else}} const navigate = useNavigate(); const [searchParams] = useSearchParams(); {{/if}} const loaderRef = useRef(null); const isLoadingRef = useRef(false); const [isVisible, setIsVisible] = useState(false); const [currentPage, setCurrentPage] = useState(() => { const page = searchParams?.get("page"); return page ? Number(page) : 1; }); useEffect(() => { isLoadingRef.current = false; }, []); useEffect(() => { if (!hasNextPage) return; const observer = new IntersectionObserver( (entries) => { const [entry] = entries; setIsVisible(entry.isIntersecting); if (entry.isIntersecting && !isLoadingRef.current && hasNextPage) { isLoadingRef.current = true; setTimeout(() => { const nextPage = currentPage + 1; setCurrentPage(nextPage); const url = formUrlQuery({ params: searchParams?.toString() ?? "", key: "page", value: nextPage.toString(), }); {{#if framework == "nextjs"}} router.push(url, { scroll: false }); {{else}} navigate(url, { replace: false }); {{/if}} }, 500); } }, { threshold: 0.8, rootMargin: "400px" }, ); if (loaderRef.current) observer.observe(loaderRef.current); return () => observer.disconnect(); }, [ hasNextPage, currentPage, {{#if framework == "nextjs"}} router, {{else}} navigate, {{/if}} searchParams, ]); return (
{isVisible && (
Loading more ...
)}
); }; export default LoadMore;