2025-05-28 15:36:51 -07:00

106 lines
4.0 KiB
JavaScript

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;
}