UNPKG

react-query

Version:

Hooks for managing, caching and syncing asynchronous and remote data in React

124 lines (108 loc) 5.73 kB
import { getAbortController } from './utils'; export function infiniteQueryBehavior() { return { onFetch: context => { context.fetchFn = () => { var _context$fetchOptions, _context$fetchOptions2, _context$fetchOptions3, _context$fetchOptions4, _context$state$data, _context$state$data2, _context$signal; const refetchPage = (_context$fetchOptions = context.fetchOptions) == null ? void 0 : (_context$fetchOptions2 = _context$fetchOptions.meta) == null ? void 0 : _context$fetchOptions2.refetchPage; const fetchMore = (_context$fetchOptions3 = context.fetchOptions) == null ? void 0 : (_context$fetchOptions4 = _context$fetchOptions3.meta) == null ? void 0 : _context$fetchOptions4.fetchMore; const pageParam = fetchMore == null ? void 0 : fetchMore.pageParam; const isFetchingNextPage = (fetchMore == null ? void 0 : fetchMore.direction) === 'forward'; const isFetchingPreviousPage = (fetchMore == null ? void 0 : fetchMore.direction) === 'backward'; const oldPages = ((_context$state$data = context.state.data) == null ? void 0 : _context$state$data.pages) || []; const oldPageParams = ((_context$state$data2 = context.state.data) == null ? void 0 : _context$state$data2.pageParams) || []; const abortController = getAbortController(); const abortSignal = abortController == null ? void 0 : abortController.signal; let newPageParams = oldPageParams; let cancelled = false; // Get query function const queryFn = context.options.queryFn || (() => Promise.reject('Missing queryFn')); const buildNewPages = (pages, param, page, previous) => { newPageParams = previous ? [param, ...newPageParams] : [...newPageParams, param]; return previous ? [page, ...pages] : [...pages, page]; }; // Create function to fetch a page const fetchPage = (pages, manual, param, previous) => { if (cancelled) { return Promise.reject('Cancelled'); } if (typeof param === 'undefined' && !manual && pages.length) { return Promise.resolve(pages); } const queryFnContext = { queryKey: context.queryKey, signal: abortSignal, pageParam: param, meta: context.meta }; const queryFnResult = queryFn(queryFnContext); const promise = Promise.resolve(queryFnResult).then(page => buildNewPages(pages, param, page, previous)); return promise; }; let promise; // Fetch first page? if (!oldPages.length) { promise = fetchPage([]); } // Fetch next page? else if (isFetchingNextPage) { const manual = typeof pageParam !== 'undefined'; const param = manual ? pageParam : getNextPageParam(context.options, oldPages); promise = fetchPage(oldPages, manual, param); } // Fetch previous page? else if (isFetchingPreviousPage) { const manual = typeof pageParam !== 'undefined'; const param = manual ? pageParam : getPreviousPageParam(context.options, oldPages); promise = fetchPage(oldPages, manual, param, true); } // Refetch pages else { newPageParams = []; const manual = typeof context.options.getNextPageParam === 'undefined'; const shouldFetchFirstPage = refetchPage && oldPages[0] ? refetchPage(oldPages[0], 0, oldPages) : true; // Fetch first page promise = shouldFetchFirstPage ? fetchPage([], manual, oldPageParams[0]) : Promise.resolve(buildNewPages([], oldPageParams[0], oldPages[0])); // Fetch remaining pages for (let i = 1; i < oldPages.length; i++) { promise = promise.then(pages => { const shouldFetchNextPage = refetchPage && oldPages[i] ? refetchPage(oldPages[i], i, oldPages) : true; if (shouldFetchNextPage) { const param = manual ? oldPageParams[i] : getNextPageParam(context.options, pages); return fetchPage(pages, manual, param); } return Promise.resolve(buildNewPages(pages, oldPageParams[i], oldPages[i])); }); } } const finalPromise = promise.then(pages => ({ pages, pageParams: newPageParams })); (_context$signal = context.signal) == null ? void 0 : _context$signal.addEventListener('abort', () => { cancelled = true; abortController == null ? void 0 : abortController.abort(); }); return finalPromise; }; } }; } export function getNextPageParam(options, pages) { return options.getNextPageParam == null ? void 0 : options.getNextPageParam(pages[pages.length - 1], pages); } export function getPreviousPageParam(options, pages) { return options.getPreviousPageParam == null ? void 0 : options.getPreviousPageParam(pages[0], pages); } /** * Checks if there is a next page. * Returns `undefined` if it cannot be determined. */ export function hasNextPage(options, pages) { if (options.getNextPageParam && Array.isArray(pages)) { const nextPageParam = getNextPageParam(options, pages); return typeof nextPageParam !== 'undefined' && nextPageParam !== null && nextPageParam !== false; } } /** * Checks if there is a previous page. * Returns `undefined` if it cannot be determined. */ export function hasPreviousPage(options, pages) { if (options.getPreviousPageParam && Array.isArray(pages)) { const previousPageParam = getPreviousPageParam(options, pages); return typeof previousPageParam !== 'undefined' && previousPageParam !== null && previousPageParam !== false; } }