diff --git a/lib/hooks/index.js b/lib/hooks/index.js index de52ae13..b8fb65aa 100644 --- a/lib/hooks/index.js +++ b/lib/hooks/index.js @@ -11,6 +11,7 @@ export { default as useInterfaceCredentials } from './useInterfaceCredentials'; export { default as useSingleFetchInterfaceCredentials } from './useSingleFetchInterfaceCredentials'; export { default as useChunkedCQLFetch } from './useChunkedCQLFetch'; export { default as useChunkedUsers } from './useChunkedUsers'; +export { default as useFetchMultiplePages } from './useFetchMultiplePages'; export { default as useParallelBatchFetch } from './useParallelBatchFetch'; export { default as usePrevNextPagination } from './usePrevNextPagination'; export { default as usePrevious } from './usePrevious'; diff --git a/lib/hooks/useFetchMultiplePages.js b/lib/hooks/useFetchMultiplePages.js new file mode 100644 index 00000000..aadc3c01 --- /dev/null +++ b/lib/hooks/useFetchMultiplePages.js @@ -0,0 +1,58 @@ +import { useMemo } from 'react'; +import { useQueries } from 'react-query'; +import { useOkapiKy } from '@folio/stripes/core'; +import { generateKiwtQueryParams } from '@k-int/stripes-kint-components'; + +const defaultParams = { page: 1 }; + +const useFetchMultiplePages = ({ + getQueryKey = ({ params, pathStr, pageNum }) => [pathStr, pageNum, params], + params = {}, // Accepts an object of the shape expected by the first parameter of generateKiwtQueryParams + path = '', + // At some point in the future I'd like this to be able to accept a list of pages, and run those all in parallel (possibly with some chunking logic) +} = {}) => { + const ky = useOkapiKy(); + const queryArray = []; + + // Apply defaultParams ensuring that 'page' is defaulted properly + const effectiveParams = useMemo(() => ({ ...defaultParams, ...params }), [params]); + + const currentPageParams = useMemo(() => ( + generateKiwtQueryParams( + { ...effectiveParams }, + {} + ) + ), [effectiveParams]); + queryArray.push({ + queryKey: getQueryKey({ + params: currentPageParams, + pageNum: effectiveParams.page, + pathStr: path + }), + queryFn: () => ky.get(`${path}?${currentPageParams?.join('&')}`).json(), + }); + + const nextPageParams = useMemo(() => ( + generateKiwtQueryParams( + { ...effectiveParams, page: effectiveParams.page + 1 }, + {} + ) + ), [effectiveParams]); + queryArray.push({ + queryKey: getQueryKey({ + params: nextPageParams, + pageNum: effectiveParams.page + 1, + pathStr: path + }), + queryFn: () => ky.get(`${path}?${nextPageParams?.join('&')}`).json(), + }); + + const queries = useQueries(queryArray); + + return ({ + [effectiveParams.page]: queries[0], + [effectiveParams.page + 1]: queries[1], // For now this is just "current" and "next", but longer term this could be expanded to n pages from a list for prefetching etc + }); +}; + +export default useFetchMultiplePages; diff --git a/lib/hooks/usePrevNextPagination.js b/lib/hooks/usePrevNextPagination.js index 7b7ddf49..cd8cea0b 100644 --- a/lib/hooks/usePrevNextPagination.js +++ b/lib/hooks/usePrevNextPagination.js @@ -12,12 +12,16 @@ import { import useLocalPageStore from './useLocalPageStore'; +// Currently there are several places in which this hook is used twice within the same component +// Once in order to get the current page, and again in order to handle changes to paginations +// This hook should be refactored in order to resolve these issue - @EthanFreestone const usePrevNextPagination = ({ count = 0, // Only needed for reading back MCL props defaultToPageOne = true, // A prop to allow the implementor to turn off the defaulting to page=1 pageSize = DEFAULT_PAGINATION_SIZE, // Only needed for reading back MCL props id = DEFAULT_PAGE_KEY, // This id is ONLY used for syncToLocation: false cases, as a key to the zustand store - syncToLocation = true // Used to turn on/off location syncing, so can be used as standalone state if required + syncToLocation = true, // Used to turn on/off location syncing, so can be used as standalone state if required, + hasNextPage = null // Override for canGoNext, used in the case in which resources are fetched with no stats } = {}) => { /* ------ ZUSTAND STORE ------ */ // For NON-SYNC-TO-LOCATION use cases, store the currentPage in a keyed store @@ -146,7 +150,7 @@ const usePrevNextPagination = ({ ]); // Set up MCL specific props based on page - const pagingCanGoNext = currentPage && currentPage < Number(count) / pageSize; + const pagingCanGoNext = hasNextPage ?? (currentPage && (currentPage < Number(count) / pageSize)); const pagingCanGoPrevious = currentPage && Number(currentPage) > 1; const pagingOffset = currentPage ? (currentPage - 1) * pageSize : 0; const onNeedMoreData = (...args) => {