import React from 'react'; import { notifyManager } from '../core/notifyManager'; import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'; import { useQueryClient } from './QueryClientProvider'; import { shouldThrowError } from './utils'; export function useBaseQuery(options, Observer) { var mountedRef = React.useRef(false); var _React$useState = React.useState(0), forceUpdate = _React$useState[1]; var queryClient = useQueryClient(); var errorResetBoundary = useQueryErrorResetBoundary(); var defaultedOptions = queryClient.defaultQueryObserverOptions(options); // Make sure results are optimistically set in fetching state before subscribing or updating options defaultedOptions.optimisticResults = true; // Include callbacks in batch renders if (defaultedOptions.onError) { defaultedOptions.onError = notifyManager.batchCalls(defaultedOptions.onError); } if (defaultedOptions.onSuccess) { defaultedOptions.onSuccess = notifyManager.batchCalls(defaultedOptions.onSuccess); } if (defaultedOptions.onSettled) { defaultedOptions.onSettled = notifyManager.batchCalls(defaultedOptions.onSettled); } if (defaultedOptions.suspense) { // Always set stale time when using suspense to prevent // fetching again when directly mounting after suspending if (typeof defaultedOptions.staleTime !== 'number') { defaultedOptions.staleTime = 1000; } // Set cache time to 1 if the option has been set to 0 // when using suspense to prevent infinite loop of fetches if (defaultedOptions.cacheTime === 0) { defaultedOptions.cacheTime = 1; } } if (defaultedOptions.suspense || defaultedOptions.useErrorBoundary) { // Prevent retrying failed query if the error boundary has not been reset yet if (!errorResetBoundary.isReset()) { defaultedOptions.retryOnMount = false; } } var _React$useState2 = React.useState(function () { return new Observer(queryClient, defaultedOptions); }), observer = _React$useState2[0]; var result = observer.getOptimisticResult(defaultedOptions); React.useEffect(function () { mountedRef.current = true; errorResetBoundary.clearReset(); var unsubscribe = observer.subscribe(notifyManager.batchCalls(function () { if (mountedRef.current) { forceUpdate(function (x) { return x + 1; }); } })); // Update result to make sure we did not miss any query updates // between creating the observer and subscribing to it. observer.updateResult(); return function () { mountedRef.current = false; unsubscribe(); }; }, [errorResetBoundary, observer]); React.useEffect(function () { // Do not notify on updates because of changes in the options because // these changes should already be reflected in the optimistic result. observer.setOptions(defaultedOptions, { listeners: false }); }, [defaultedOptions, observer]); // Handle suspense if (defaultedOptions.suspense && result.isLoading) { throw observer.fetchOptimistic(defaultedOptions).then(function (_ref) { var data = _ref.data; defaultedOptions.onSuccess == null ? void 0 : defaultedOptions.onSuccess(data); defaultedOptions.onSettled == null ? void 0 : defaultedOptions.onSettled(data, null); }).catch(function (error) { errorResetBoundary.clearReset(); defaultedOptions.onError == null ? void 0 : defaultedOptions.onError(error); defaultedOptions.onSettled == null ? void 0 : defaultedOptions.onSettled(undefined, error); }); } // Handle error boundary if (result.isError && !errorResetBoundary.isReset() && !result.isFetching && shouldThrowError(defaultedOptions.suspense, defaultedOptions.useErrorBoundary, [result.error, observer.getCurrentQuery()])) { throw result.error; } // Handle result property usage tracking if (defaultedOptions.notifyOnChangeProps === 'tracked') { result = observer.trackResult(result, defaultedOptions); } return result; }