diff --git a/.changeset/fuzzy-rats-mutate.md b/.changeset/fuzzy-rats-mutate.md new file mode 100644 index 00000000000..fafbc165772 --- /dev/null +++ b/.changeset/fuzzy-rats-mutate.md @@ -0,0 +1,5 @@ +--- +'@tanstack/react-query': patch +--- + +Allow queries with falsy errors to retry on mount when `throwOnError` returns false. diff --git a/packages/react-query/src/__tests__/useQuery.test.tsx b/packages/react-query/src/__tests__/useQuery.test.tsx index 520e80fc673..ab15a3aa454 100644 --- a/packages/react-query/src/__tests__/useQuery.test.tsx +++ b/packages/react-query/src/__tests__/useQuery.test.tsx @@ -6802,6 +6802,35 @@ describe('useQuery', () => { expect(queryFn).toHaveBeenCalledTimes(2) }) + it('should retry on mount when throwOnError returns false for a falsy error', async () => { + const key = queryKey() + const queryFn = vi.fn(() => Promise.reject()) + + function Component() { + const { status } = useQuery({ + queryKey: key, + queryFn, + throwOnError: () => false, + retryOnMount: () => true, + staleTime: Infinity, + retry: false, + }) + + return
{status}
+ } + + const rendered1 = renderWithClient(queryClient, ) + await vi.advanceTimersByTimeAsync(0) + expect(rendered1.getByTestId('status')).toHaveTextContent('error') + expect(queryFn).toHaveBeenCalledTimes(1) + rendered1.unmount() + + const rendered2 = renderWithClient(queryClient, ) + await vi.advanceTimersByTimeAsync(0) + expect(rendered2.getByTestId('status')).toHaveTextContent('error') + expect(queryFn).toHaveBeenCalledTimes(2) + }) + it('should not retry on mount when throwOnError function returns true', async () => { const key = queryKey() let fetchCount = 0 diff --git a/packages/react-query/src/errorBoundaryUtils.ts b/packages/react-query/src/errorBoundaryUtils.ts index a27036f9a2c..f1170c17c8e 100644 --- a/packages/react-query/src/errorBoundaryUtils.ts +++ b/packages/react-query/src/errorBoundaryUtils.ts @@ -27,10 +27,14 @@ export const ensurePreventErrorBoundaryRetry = < errorResetBoundary: QueryErrorResetBoundaryValue, query: Query | undefined, ) => { - const throwOnError = - query?.state.error && typeof options.throwOnError === 'function' - ? shouldThrowError(options.throwOnError, [query.state.error, query]) - : options.throwOnError + let throwOnError = options.throwOnError + + if (query?.state.status === 'error' && typeof throwOnError === 'function') { + throwOnError = shouldThrowError(throwOnError, [ + query.state.error as TError, + query, + ]) + } if (options.suspense || throwOnError) { // Prevent retrying failed query if the error boundary has not been reset yet