create-plume-react-project
Version:
CLI to create Plume React Project
75 lines (68 loc) • 2.69 kB
text/typescript
import useNotification, { PlumeNotification } from '@lib/plume-notification/NotificationHook';
import {
Page, PaginationParamsType, PaginationType, PaginatedSearch,
} from '@lib/plume-search/SearchTypes';
import { SortOption } from '@lib/plume-search/sorts/SortTypes';
import { useEffect, useState } from 'react';
import { HttpPromise } from 'simple-http-rest-client';
import usePagination from './pagination/PaginationHook';
type SearchLazyLoadedDataOptions<TFilter, TSort extends string> = {
filterValues: Partial<TFilter>,
sort: SortOption<TSort>,
defaultPageSize: number,
};
/**
* Hook to handle API call search with pagination
* This search relies on results and pagination provided by the API call
*
* @param loadData the paginated search API call
* @param options the options to apply to the search
* @return displayedItems the elements to display
* @return totalCount total elements of the list you are paginating
* @return hasMore boolean set to false if at the end of the list you are paginating
* @return onDisplayMore function to call to display the next page of the list you are paginating
*/
function useApiPaginatedSearch<TData, TFilter, TSort extends string>(
loadData: (
filterValues: Partial<TFilter>,
sort: SortOption<TSort> | undefined,
pagination: PaginationParamsType | undefined,
) => HttpPromise<Page<TData>>,
options: Partial<SearchLazyLoadedDataOptions<TFilter, TSort>>,
): PaginatedSearch<TData> {
const { notifyHttpError }: PlumeNotification = useNotification();
const [elements, setElements] = useState<TData[]>([]);
const [totalCount, setTotalCount] = useState<number>(0);
const [hasMore, setHasMore] = useState<boolean>(false);
const pagination: PaginationType = usePagination({ pageSize: options?.defaultPageSize ?? 10 });
const loadPage = (pageNumber: number) => {
pagination.setPage(pageNumber);
loadData(
options?.filterValues ?? {},
options?.sort,
{
page: pageNumber,
limit: pagination.pageSize,
},
)
.then((page: Page<TData>) => {
setElements((currentElements: TData[]) => [...currentElements, ...page.items]);
setTotalCount(page.totalCount);
setHasMore(page.hasMore);
pagination.setElementCount(page.totalCount);
})
.catch(notifyHttpError);
};
useEffect(() => {
setElements([]);
loadPage(1);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [options?.filterValues ?? {}, options?.sort ?? {}]);
return {
displayedItems: elements,
totalCount,
hasMore,
onDisplayMore: () => loadPage(pagination.currentPage + 1),
};
}
export default useApiPaginatedSearch;