/* eslint-disable react-hooks/exhaustive-deps */ import React, { useState, useEffect } from "react"; // Tipe untuk data item (sesuaikan sesuai API kamu) interface Item { id: number; name: string; } // Props komponen interface InfiniteScrollProps { fetchFunction: (page: number) => Promise; renderItem: (item: T) => React.ReactNode; itemsPerPage?: number; threshold?: number; // Jarak dari bawah halaman untuk memicu load } const InfiniteScroll = ({ fetchFunction, renderItem, itemsPerPage = 10, threshold = 50, }: InfiniteScrollProps) => { const [items, setItems] = useState([]); const [hasMore, setHasMore] = useState(true); const [page, setPage] = useState(1); // Load data awal useEffect(() => { const loadInitialData = async () => { const data = await fetchFunction(page); if (data.length === 0) setHasMore(false); setItems(data); }; loadInitialData(); }, [fetchFunction, page]); // Handle scroll event useEffect(() => { const handleScroll = () => { const isBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - threshold; if (isBottom && hasMore) { loadMoreItems(); } }; window.addEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll); }, [hasMore, threshold]); const loadMoreItems = async () => { const nextPage = page + 1; const newItems = await fetchFunction(nextPage); if (newItems.length === 0) { setHasMore(false); } setItems((prev) => [...prev, ...newItems]); setPage(nextPage); }; return (
    {items.map((item, index) => (
  • {renderItem(item)}
  • ))}
{!hasMore &&

🎉 Semua data telah dimuat.

}
); }; export default InfiniteScroll;