UNPKG

@tanstack/react-query

Version:

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

83 lines (71 loc) 3.68 kB
import * as React from 'react'; import { useSyncExternalStore } from './useSyncExternalStore.esm.js'; import { QueriesObserver, notifyManager } from '@tanstack/query-core'; import { useQueryClient } from './QueryClientProvider.esm.js'; import { useIsRestoring } from './isRestoring.esm.js'; import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary.esm.js'; import { ensurePreventErrorBoundaryRetry, useClearResetErrorBoundary, getHasError } from './errorBoundaryUtils.esm.js'; import { ensureStaleTime, shouldSuspend, fetchOptimistic, willFetch } from './suspense.esm.js'; // - `context` is omitted as it is passed as a root-level option to `useQueries` instead. function useQueries({ queries, context }) { const queryClient = useQueryClient({ context }); const isRestoring = useIsRestoring(); const errorResetBoundary = useQueryErrorResetBoundary(); const defaultedQueries = React.useMemo(() => queries.map(options => { const defaultedOptions = queryClient.defaultQueryOptions(options); // Make sure the results are already in fetching state before subscribing or updating options defaultedOptions._optimisticResults = isRestoring ? 'isRestoring' : 'optimistic'; return defaultedOptions; }), [queries, queryClient, isRestoring]); defaultedQueries.forEach(query => { ensureStaleTime(query); ensurePreventErrorBoundaryRetry(query, errorResetBoundary); }); useClearResetErrorBoundary(errorResetBoundary); const [observer] = React.useState(() => new QueriesObserver(queryClient, defaultedQueries)); const optimisticResult = observer.getOptimisticResult(defaultedQueries); useSyncExternalStore(React.useCallback(onStoreChange => isRestoring ? () => undefined : observer.subscribe(notifyManager.batchCalls(onStoreChange)), [observer, isRestoring]), () => observer.getCurrentResult(), () => observer.getCurrentResult()); React.useEffect(() => { // Do not notify on updates because of changes in the options because // these changes should already be reflected in the optimistic result. observer.setQueries(defaultedQueries, { listeners: false }); }, [defaultedQueries, observer]); const shouldAtLeastOneSuspend = optimisticResult.some((result, index) => shouldSuspend(defaultedQueries[index], result, isRestoring)); const suspensePromises = shouldAtLeastOneSuspend ? optimisticResult.flatMap((result, index) => { const options = defaultedQueries[index]; const queryObserver = observer.getObservers()[index]; if (options && queryObserver) { if (shouldSuspend(options, result, isRestoring)) { return fetchOptimistic(options, queryObserver, errorResetBoundary); } else if (willFetch(result, isRestoring)) { void fetchOptimistic(options, queryObserver, errorResetBoundary); } } return []; }) : []; if (suspensePromises.length > 0) { throw Promise.all(suspensePromises); } const observerQueries = observer.getQueries(); const firstSingleResultWhichShouldThrow = optimisticResult.find((result, index) => { var _defaultedQueries$ind, _defaultedQueries$ind2; return getHasError({ result, errorResetBoundary, useErrorBoundary: (_defaultedQueries$ind = (_defaultedQueries$ind2 = defaultedQueries[index]) == null ? void 0 : _defaultedQueries$ind2.useErrorBoundary) != null ? _defaultedQueries$ind : false, query: observerQueries[index] }); }); if (firstSingleResultWhichShouldThrow != null && firstSingleResultWhichShouldThrow.error) { throw firstSingleResultWhichShouldThrow.error; } return optimisticResult; } export { useQueries }; //# sourceMappingURL=useQueries.esm.js.map