'use client'; import { useCallback, useEffect, useRef, useState, useTransition } from 'react'; import Spinner from './Spinner'; export default function MoreComponents({ itemsPerRequest, itemsTotalCount, componentLoader, label = 'Load more', triggerOnView = true, }: { itemsPerRequest: number itemsTotalCount: number componentLoader: (limit: number) => Promise label?: string triggerOnView?: boolean prefetch?: boolean }) { const [offset, setOffset] = useState(1); const [components, setComponents] = useState([]); const [isPending, startTransition] = useTransition(); const buttonRef = useRef(null); const advance = useCallback(() => startTransition(() => { setOffset(o => o + 1); }), []); useEffect(() => { const getMoreComponentsAsync = async () => { console.log('getMoreComponentsAsync', itemsPerRequest * offset); return componentLoader(itemsPerRequest * offset); }; getMoreComponentsAsync().then((component) => { setComponents([component]); }); }, [componentLoader, itemsPerRequest, offset]); useEffect(() => { // Only add observer if button is rendered if (buttonRef.current) { const observer = new IntersectionObserver(e => { if ( triggerOnView && e[0].isIntersecting && !isPending ) { advance(); } }, { root: null, threshold: 0, }); observer.observe(buttonRef.current); return () => observer.disconnect(); } }, [triggerOnView, advance, isPending]); const showMoreButton = itemsTotalCount > itemsPerRequest * offset; return
{components} {showMoreButton && }
; }