diff --git a/src/hooks/api.ts b/src/hooks/api.ts new file mode 100644 index 00000000..aba6c8e3 --- /dev/null +++ b/src/hooks/api.ts @@ -0,0 +1,49 @@ +import type { TypedUseLazyQuery } from "@reduxjs/toolkit/query/react" +import { useEffect, useState } from "react" + +import type { Fields, ListArg, ListResult, Model } from "../utils/api" + +export function useFullList< + QueryArg extends ListArg, + M extends Model, + MFields extends keyof Omit, + ExtraFields extends Fields, + ResultType extends ListResult, +>( + useLazyListQuery: TypedUseLazyQuery, + arg: Partial = {}, +) { + const { limit = 150, offset = 0, ...filters } = arg + + const [trigger] = useLazyListQuery() + const [isLoading, setIsLoading] = useState(true) + const [isError, setIsError] = useState(false) + const [error, setError] = useState() + const [data, setData] = useState() + + function getPage(limit: number, offset: number, _data: ResultType["data"]) { + trigger({ ...filters, limit, offset } as QueryArg) + .unwrap() + .then(({ data, offset, limit, count }) => { + _data.push(...data) + + offset += limit + if (offset < count) getPage(limit, offset, _data) + else { + setData(_data) + setIsLoading(false) + } + }) + .catch(error => { + setError(error) + setIsError(true) + }) + } + + useEffect(() => { + getPage(limit, offset, []) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [limit, offset]) + + return { data, isLoading, isError, error } +} diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 11ca21a5..ce45825e 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,3 +1,4 @@ +import { useFullList } from "./api" import { useSession, useSessionMetadata, @@ -13,6 +14,7 @@ export { useCountdown, useEventListener, useExternalScript, + useFullList, useLocation, useNavigate, useParams,