Skip to content

Commit 088ec87

Browse files
authored
fix(useSuspenseQuery): throw select errors to ErrorBoundary (#8593)
1 parent c6af7a5 commit 088ec87

File tree

4 files changed

+49
-1
lines changed

4 files changed

+49
-1
lines changed

packages/react-query/src/__tests__/useSuspenseQuery.test.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,49 @@ describe('useSuspenseQuery', () => {
515515
consoleMock.mockRestore()
516516
})
517517

518+
it('should throw select errors to the error boundary by default', async () => {
519+
const consoleMock = vi
520+
.spyOn(console, 'error')
521+
.mockImplementation(() => undefined)
522+
const key = queryKey()
523+
524+
function Page() {
525+
useSuspenseQuery({
526+
queryKey: key,
527+
queryFn: () => {
528+
const data = { a: { b: 'c' } }
529+
return Promise.resolve(data)
530+
},
531+
select: () => {
532+
throw new Error('foo')
533+
},
534+
})
535+
return <div>rendered</div>
536+
}
537+
538+
function App() {
539+
return (
540+
<ErrorBoundary
541+
fallbackRender={() => (
542+
<div>
543+
<div>error boundary</div>
544+
</div>
545+
)}
546+
>
547+
<React.Suspense fallback="Loading...">
548+
<Page />
549+
</React.Suspense>
550+
</ErrorBoundary>
551+
)
552+
}
553+
554+
const rendered = renderWithClient(queryClient, <App />)
555+
556+
await waitFor(() => rendered.getByText('Loading...'))
557+
await waitFor(() => rendered.getByText('error boundary'))
558+
consoleMock.mockRestore()
559+
})
560+
518561
it('should error caught in error boundary without infinite loop', async () => {
519562
const consoleMock = vi
520563
.spyOn(console, 'error')

packages/react-query/src/errorBoundaryUtils.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,20 @@ export const getHasError = <
5757
errorResetBoundary,
5858
throwOnError,
5959
query,
60+
suspense,
6061
}: {
6162
result: QueryObserverResult<TData, TError>
6263
errorResetBoundary: QueryErrorResetBoundaryValue
6364
throwOnError: ThrowOnError<TQueryFnData, TError, TQueryData, TQueryKey>
6465
query: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined
66+
suspense: boolean | undefined
6567
}) => {
6668
return (
6769
result.isError &&
6870
!errorResetBoundary.isReset() &&
6971
!result.isFetching &&
7072
query &&
71-
shouldThrowError(throwOnError, [result.error, query])
73+
((suspense && result.data === undefined) ||
74+
shouldThrowError(throwOnError, [result.error, query]))
7275
)
7376
}

packages/react-query/src/useBaseQuery.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export function useBaseQuery<
130130
TQueryData,
131131
TQueryKey
132132
>(defaultedOptions.queryHash),
133+
suspense: defaultedOptions.suspense,
133134
})
134135
) {
135136
throw result.error

packages/react-query/src/useQueries.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ export function useQueries<
337337
errorResetBoundary,
338338
throwOnError: query.throwOnError,
339339
query: client.getQueryCache().get(query.queryHash),
340+
suspense: defaultedQueries[index]?.suspense,
340341
})
341342
)
342343
},

0 commit comments

Comments
 (0)