import { useCallback, useEffect, useMemo, useRef, useState } from "react"; export default function usePaginatedList(fetchFn, extraParams = {}) { const [rows, setRows] = useState([]); const [search, setSearch] = useState(""); const [debouncedSearch, setDebouncedSearch] = useState(""); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(12); const [totalCount, setTotalCount] = useState(0); const [loading, setLoading] = useState(true); const [err, setErr] = useState(""); const debounceRef = useRef(null); const extraKey = JSON.stringify(extraParams); useEffect(() => { if (debounceRef.current) clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { setDebouncedSearch(search); setPage(1); }, 600); return () => clearTimeout(debounceRef.current); }, [search]); const reload = useCallback(() => { setLoading(true); setErr(""); fetchFn({ search: debouncedSearch, page, pageSize, ...extraParams }) .then(({ rows, totalCount }) => { setRows(rows); setTotalCount(totalCount); }) .catch((e) => setErr(e.message || "Failed to load")) .finally(() => setLoading(false)); }, [fetchFn, debouncedSearch, page, pageSize, extraKey]); useEffect(() => { reload(); }, [reload]); return useMemo(() => ({ rows, search, setSearch, page, setPage, pageSize, setPageSize, totalCount, loading, err, reload }), [rows, search, page, pageSize, totalCount, loading, err, reload]); }