Skip to content

Commit 1beedf9

Browse files
authored
fix(core): make sure erroneous queries refetch when query keys change (#2686)
1 parent 7aadd68 commit 1beedf9

File tree

2 files changed

+82
-17
lines changed

2 files changed

+82
-17
lines changed

src/core/queryObserver.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,9 @@ function shouldFetchOptionally(
768768
return (
769769
options.enabled !== false &&
770770
(query !== prevQuery || prevOptions.enabled === false) &&
771-
(query.state.status !== 'error' || prevOptions.enabled === false) &&
771+
(!options.suspense ||
772+
query.state.status !== 'error' ||
773+
prevOptions.enabled === false) &&
772774
isStale(query, options)
773775
)
774776
}

src/react/tests/useQuery.test.tsx

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4066,23 +4066,25 @@ describe('useQuery', () => {
40664066

40674067
it('should refetch when query key changed when previous status is error', async () => {
40684068
const consoleMock = mockConsoleError()
4069-
const queryFn = jest.fn()
40704069

40714070
function Page({ id }: { id: number }) {
4072-
queryFn.mockImplementation(async () => {
4073-
await sleep(10)
4074-
if (id % 2 === 1) {
4075-
return Promise.reject(new Error('Suspense Error Bingo'))
4076-
} else {
4077-
return 'data'
4071+
const { error, isLoading } = useQuery(
4072+
[id],
4073+
async () => {
4074+
await sleep(10)
4075+
if (id % 2 === 1) {
4076+
return Promise.reject(new Error('Error'))
4077+
} else {
4078+
return 'data'
4079+
}
4080+
},
4081+
{
4082+
retry: false,
4083+
retryOnMount: false,
4084+
refetchOnMount: false,
4085+
refetchOnWindowFocus: false,
40784086
}
4079-
})
4080-
const { error, isLoading } = useQuery([id], queryFn, {
4081-
retry: false,
4082-
retryOnMount: false,
4083-
refetchOnMount: false,
4084-
refetchOnWindowFocus: false,
4085-
})
4087+
)
40864088

40874089
if (isLoading) {
40884090
return <div>status: loading</div>
@@ -4114,12 +4116,73 @@ describe('useQuery', () => {
41144116
// render error state component
41154117
await waitFor(() => rendered.getByText('error'))
41164118

4117-
// change to enabled to false
4119+
// change to unmount query
41184120
fireEvent.click(rendered.getByLabelText('change'))
41194121
await waitFor(() => rendered.getByText('rendered'))
41204122

4121-
// // change to enabled to true
4123+
// change to mount new query
4124+
fireEvent.click(rendered.getByLabelText('change'))
4125+
await waitFor(() => rendered.getByText('error'))
4126+
4127+
consoleMock.mockRestore()
4128+
})
4129+
4130+
it('should refetch when query key changed when switching between erroneous queries', async () => {
4131+
const consoleMock = mockConsoleError()
4132+
4133+
function Page({ id }: { id: boolean }) {
4134+
const { error, isFetching } = useQuery(
4135+
[id],
4136+
async () => {
4137+
await sleep(10)
4138+
return Promise.reject(new Error('Error'))
4139+
},
4140+
{
4141+
retry: false,
4142+
retryOnMount: false,
4143+
refetchOnMount: false,
4144+
refetchOnWindowFocus: false,
4145+
}
4146+
)
4147+
4148+
if (isFetching) {
4149+
return <div>status: fetching</div>
4150+
}
4151+
if (error instanceof Error) {
4152+
return <div>error</div>
4153+
}
4154+
return <div>rendered</div>
4155+
}
4156+
4157+
function App() {
4158+
const [value, toggle] = React.useReducer(x => !x, true)
4159+
4160+
return (
4161+
<div>
4162+
<Page id={value} />
4163+
<button aria-label="change" onClick={toggle}>
4164+
change {value}
4165+
</button>
4166+
</div>
4167+
)
4168+
}
4169+
4170+
const rendered = renderWithClient(queryClient, <App />)
4171+
4172+
// initial state check
4173+
rendered.getByText('status: fetching')
4174+
4175+
// render error state component
4176+
await waitFor(() => rendered.getByText('error'))
4177+
4178+
// change to mount second query
4179+
fireEvent.click(rendered.getByLabelText('change'))
4180+
await waitFor(() => rendered.getByText('status: fetching'))
4181+
await waitFor(() => rendered.getByText('error'))
4182+
4183+
// change to mount first query again
41224184
fireEvent.click(rendered.getByLabelText('change'))
4185+
await waitFor(() => rendered.getByText('status: fetching'))
41234186
await waitFor(() => rendered.getByText('error'))
41244187

41254188
consoleMock.mockRestore()

0 commit comments

Comments
 (0)