UNPKG

@tanstack/react-query

Version:

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

98 lines (97 loc) 3.72 kB
"use client"; // src/useBaseQuery.ts import * as React from "react"; import { isServer, notifyManager } from "@tanstack/query-core"; import { useQueryClient } from "./QueryClientProvider.js"; import { useQueryErrorResetBoundary } from "./QueryErrorResetBoundary.js"; import { ensurePreventErrorBoundaryRetry, getHasError, useClearResetErrorBoundary } from "./errorBoundaryUtils.js"; import { useIsRestoring } from "./isRestoring.js"; import { ensureSuspenseTimers, fetchOptimistic, shouldSuspend, willFetch } from "./suspense.js"; import { noop } from "./utils.js"; function useBaseQuery(options, Observer, queryClient) { if (process.env.NODE_ENV !== "production") { if (typeof options !== "object" || Array.isArray(options)) { throw new Error( 'Bad argument type. Starting with v5, only the "Object" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object' ); } } const client = useQueryClient(queryClient); const isRestoring = useIsRestoring(); const errorResetBoundary = useQueryErrorResetBoundary(); const defaultedOptions = client.defaultQueryOptions(options); client.getDefaultOptions().queries?._experimental_beforeQuery?.( defaultedOptions ); defaultedOptions._optimisticResults = isRestoring ? "isRestoring" : "optimistic"; ensureSuspenseTimers(defaultedOptions); ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary); useClearResetErrorBoundary(errorResetBoundary); const isNewCacheEntry = !client.getQueryCache().get(defaultedOptions.queryHash); const [observer] = React.useState( () => new Observer( client, defaultedOptions ) ); const result = observer.getOptimisticResult(defaultedOptions); const shouldSubscribe = !isRestoring && options.subscribed !== false; React.useSyncExternalStore( React.useCallback( (onStoreChange) => { const unsubscribe = shouldSubscribe ? observer.subscribe(notifyManager.batchCalls(onStoreChange)) : noop; observer.updateResult(); return unsubscribe; }, [observer, shouldSubscribe] ), () => observer.getCurrentResult(), () => observer.getCurrentResult() ); React.useEffect(() => { observer.setOptions(defaultedOptions, { listeners: false }); }, [defaultedOptions, observer]); if (shouldSuspend(defaultedOptions, result)) { throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary); } if (getHasError({ result, errorResetBoundary, throwOnError: defaultedOptions.throwOnError, query: client.getQueryCache().get(defaultedOptions.queryHash), suspense: defaultedOptions.suspense })) { throw result.error; } ; client.getDefaultOptions().queries?._experimental_afterQuery?.( defaultedOptions, result ); if (defaultedOptions.experimental_prefetchInRender && !isServer && willFetch(result, isRestoring)) { const promise = isNewCacheEntry ? ( // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted fetchOptimistic(defaultedOptions, observer, errorResetBoundary) ) : ( // subscribe to the "cache promise" so that we can finalize the currentThenable once data comes in client.getQueryCache().get(defaultedOptions.queryHash)?.promise ); promise?.catch(noop).finally(() => { observer.updateResult(); }); } return !defaultedOptions.notifyOnChangeProps ? observer.trackResult(result) : result; } export { useBaseQuery }; //# sourceMappingURL=useBaseQuery.js.map