Skip to content

Commit 0781142

Browse files
authored
fix(core): remove enabled condition in queryObserver for suspense (TanStack#3093)
* fix(core): remove enabled condition in queryObserver TanStack#2434 * chore: add missing test case * chore: fix format
1 parent 988ba10 commit 0781142

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

src/core/queryObserver.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -790,9 +790,7 @@ function shouldFetchOptionally(
790790
return (
791791
options.enabled !== false &&
792792
(query !== prevQuery || prevOptions.enabled === false) &&
793-
(!options.suspense ||
794-
query.state.status !== 'error' ||
795-
prevOptions.enabled === false) &&
793+
(!options.suspense || query.state.status !== 'error') &&
796794
isStale(query, options)
797795
)
798796
}

src/react/tests/suspense.test.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,76 @@ describe("useQuery's in Suspense mode", () => {
891891
consoleMock.mockRestore()
892892
})
893893

894+
it('should error catched in error boundary without infinite loop when enabled changed', async () => {
895+
const consoleMock = mockConsoleError()
896+
897+
const succeed = false
898+
899+
function Page() {
900+
const queryKeys = '1'
901+
const [enabled, setEnabled] = React.useState(false)
902+
903+
const result = useQuery(
904+
[queryKeys],
905+
async () => {
906+
await sleep(10)
907+
if (!succeed) {
908+
throw new Error('Suspense Error Bingo')
909+
} else {
910+
return 'data'
911+
}
912+
},
913+
{
914+
retry: false,
915+
suspense: true,
916+
enabled,
917+
}
918+
)
919+
return (
920+
<div>
921+
<span>rendered</span> <span>{result.data}</span>
922+
<button
923+
aria-label="fail"
924+
onClick={() => {
925+
setEnabled(true)
926+
}}
927+
>
928+
fail
929+
</button>
930+
</div>
931+
)
932+
}
933+
934+
function App() {
935+
const { reset } = useQueryErrorResetBoundary()
936+
return (
937+
<ErrorBoundary
938+
onReset={reset}
939+
fallbackRender={() => <div>error boundary</div>}
940+
>
941+
<React.Suspense fallback="Loading...">
942+
<Page />
943+
</React.Suspense>
944+
</ErrorBoundary>
945+
)
946+
}
947+
948+
const rendered = renderWithClient(queryClient, <App />)
949+
950+
// render empty data with 'rendered' when enabled is false
951+
await waitFor(() => rendered.getByText('rendered'))
952+
953+
// change enabled to true
954+
fireEvent.click(rendered.getByLabelText('fail'))
955+
956+
// render pending fallback
957+
await waitFor(() => rendered.getByText('Loading...'))
958+
959+
// render error boundary fallback (error boundary)
960+
await waitFor(() => rendered.getByText('error boundary'))
961+
consoleMock.mockRestore()
962+
})
963+
894964
it('should render the correct amount of times in Suspense mode when cacheTime is set to 0', async () => {
895965
const key = queryKey()
896966
let state: UseQueryResult<number> | null = null

0 commit comments

Comments
 (0)