import { useCallback, useMemo } from 'react'; import useSWRInfinite, { SWRInfiniteKeyLoader } from 'swr/infinite'; import { apiGetNotes } from '~/api/notes'; import { ApiGetNotesRequest } from '~/api/notes/types'; import { useAuth } from '~/hooks/auth/useAuth'; import { GetLabNodesRequest, ILabNode } from '~/types/lab'; import { flatten, uniqBy } from '~/utils/ramda'; const DEFAULT_COUNT = 20; const getKey: (isUser: boolean, search: string) => SWRInfiniteKeyLoader = (isUser, search) => ( index, prev: ILabNode[] ) => { if (!isUser) return null; if (index > 0 && (!prev?.length || prev.length < 20)) return null; const props: GetLabNodesRequest = { limit: DEFAULT_COUNT, offset: index * DEFAULT_COUNT, search: search || '', }; return JSON.stringify(props); }; const parseKey = (key: string): ApiGetNotesRequest => { try { return JSON.parse(key); } catch (error) { return { limit: DEFAULT_COUNT, offset: 0, search: '' }; } }; export const useGetNotes = (search: string) => { const { isUser } = useAuth(); const { data, isValidating, size, setSize, mutate } = useSWRInfinite( getKey(isUser, search), async (key: string) => { const result = await apiGetNotes(parseKey(key)); return result.list; }, { dedupingInterval: 300, } ); const notes = useMemo(() => uniqBy(n => n.id, flatten(data || [])), [data]); const hasMore = (data?.[size - 1]?.length || 0) >= 1; const loadMore = useCallback(() => setSize(size + 1), [setSize, size]); return { notes, hasMore, loadMore, isLoading: !data && isValidating }; };