Skip to content

Commit

Permalink
fix(useSuspenseQuery): throw select errors to ErrorBoundary (#8593)
Browse files Browse the repository at this point in the history
  • Loading branch information
OliverJAsh authored Jan 28, 2025
1 parent c6af7a5 commit 088ec87
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
43 changes: 43 additions & 0 deletions packages/react-query/src/__tests__/useSuspenseQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,49 @@ describe('useSuspenseQuery', () => {
consoleMock.mockRestore()
})

it('should throw select errors to the error boundary by default', async () => {
const consoleMock = vi
.spyOn(console, 'error')
.mockImplementation(() => undefined)
const key = queryKey()

function Page() {
useSuspenseQuery({
queryKey: key,
queryFn: () => {
const data = { a: { b: 'c' } }
return Promise.resolve(data)
},
select: () => {
throw new Error('foo')
},
})
return <div>rendered</div>
}

function App() {
return (
<ErrorBoundary
fallbackRender={() => (
<div>
<div>error boundary</div>
</div>
)}
>
<React.Suspense fallback="Loading...">
<Page />
</React.Suspense>
</ErrorBoundary>
)
}

const rendered = renderWithClient(queryClient, <App />)

await waitFor(() => rendered.getByText('Loading...'))
await waitFor(() => rendered.getByText('error boundary'))
consoleMock.mockRestore()
})

it('should error caught in error boundary without infinite loop', async () => {
const consoleMock = vi
.spyOn(console, 'error')
Expand Down
5 changes: 4 additions & 1 deletion packages/react-query/src/errorBoundaryUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,20 @@ export const getHasError = <
errorResetBoundary,
throwOnError,
query,
suspense,
}: {
result: QueryObserverResult<TData, TError>
errorResetBoundary: QueryErrorResetBoundaryValue
throwOnError: ThrowOnError<TQueryFnData, TError, TQueryData, TQueryKey>
query: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined
suspense: boolean | undefined
}) => {
return (
result.isError &&
!errorResetBoundary.isReset() &&
!result.isFetching &&
query &&
shouldThrowError(throwOnError, [result.error, query])
((suspense && result.data === undefined) ||
shouldThrowError(throwOnError, [result.error, query]))
)
}
1 change: 1 addition & 0 deletions packages/react-query/src/useBaseQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export function useBaseQuery<
TQueryData,
TQueryKey
>(defaultedOptions.queryHash),
suspense: defaultedOptions.suspense,
})
) {
throw result.error
Expand Down
1 change: 1 addition & 0 deletions packages/react-query/src/useQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ export function useQueries<
errorResetBoundary,
throwOnError: query.throwOnError,
query: client.getQueryCache().get(query.queryHash),
suspense: defaultedQueries[index]?.suspense,
})
)
},
Expand Down

0 comments on commit 088ec87

Please sign in to comment.