Skip to content

Commit c9873a9

Browse files
committed
fix: queries should not end up in an error state when a component unmounts
1 parent c921585 commit c9873a9

File tree

4 files changed

+17
-34
lines changed

4 files changed

+17
-34
lines changed

src/core/query.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export class Query<
129129
queryHash: string
130130
options!: QueryOptions<TQueryFnData, TError, TData>
131131
initialState: QueryState<TData, TError>
132+
revertState?: QueryState<TData, TError>
132133
state: QueryState<TData, TError>
133134
cacheTime!: number
134135

@@ -301,7 +302,7 @@ export class Query<
301302
// we'll let the query continue so the result can be cached
302303
if (this.retryer) {
303304
if (this.retryer.isTransportCancelable) {
304-
this.retryer.cancel()
305+
this.retryer.cancel({ revert: true })
305306
} else {
306307
this.retryer.cancelRetry()
307308
}
@@ -377,6 +378,9 @@ export class Query<
377378
this.options.behavior?.onFetch(context)
378379
}
379380

381+
// Store state in case the current fetch needs to be reverted
382+
this.revertState = this.state
383+
380384
// Set to fetching state if not already in it
381385
if (
382386
!this.state.isFetching ||
@@ -529,24 +533,8 @@ export class Query<
529533
case 'error':
530534
const error = action.error as unknown
531535

532-
if (isCancelledError(error) && error.revert) {
533-
let previousStatus: QueryStatus
534-
535-
if (!state.dataUpdatedAt && !state.errorUpdatedAt) {
536-
previousStatus = 'idle'
537-
} else if (state.dataUpdatedAt > state.errorUpdatedAt) {
538-
previousStatus = 'success'
539-
} else {
540-
previousStatus = 'error'
541-
}
542-
543-
return {
544-
...state,
545-
fetchFailureCount: 0,
546-
isFetching: false,
547-
isPaused: false,
548-
status: previousStatus,
549-
}
536+
if (isCancelledError(error) && error.revert && this.revertState) {
537+
return { ...this.revertState }
550538
}
551539

552540
return {

src/core/tests/query.test.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,7 @@ describe('query', () => {
247247
expect(cancel).toHaveBeenCalled()
248248
expect(query.state).toMatchObject({
249249
data: undefined,
250-
status: 'error',
251-
errorUpdateCount: 1,
250+
status: 'idle',
252251
})
253252
})
254253

src/react/tests/useInfiniteQuery.test.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
QueryClient,
1616
QueryCache,
1717
} from '../..'
18-
import { CancelledError } from '../../core'
1918

2019
interface Result {
2120
items: number[]
@@ -726,6 +725,8 @@ describe('useInfiniteQuery', () => {
726725
const states: UseInfiniteQueryResult<number>[] = []
727726
let fetches = 0
728727

728+
const initialData = { pages: [1, 2, 3, 4], pageParams: [1, 2, 3, 4] }
729+
729730
function List() {
730731
const state = useInfiniteQuery(
731732
key,
@@ -735,7 +736,7 @@ describe('useInfiniteQuery', () => {
735736
return Number(pageParam)
736737
},
737738
{
738-
initialData: { pages: [1, 2, 3, 4], pageParams: [1, 2, 3, 4] },
739+
initialData,
739740
getNextPageParam: lastPage => lastPage + 1,
740741
}
741742
)
@@ -764,8 +765,9 @@ describe('useInfiniteQuery', () => {
764765
expect(states.length).toBe(1)
765766
expect(fetches).toBe(2)
766767
expect(queryClient.getQueryState(key)).toMatchObject({
767-
status: 'error',
768-
error: expect.any(CancelledError),
768+
data: initialData,
769+
status: 'success',
770+
error: null,
769771
})
770772
})
771773

src/react/tests/useQuery.test.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
} from './utils'
1414
import {
1515
useQuery,
16-
CancelledError,
1716
QueryClient,
1817
UseQueryResult,
1918
QueryCache,
@@ -3353,7 +3352,7 @@ describe('useQuery', () => {
33533352
renderWithClient(queryClient, <Page />)
33543353

33553354
await sleep(100)
3356-
expect(states.length).toBe(5)
3355+
expect(states.length).toBe(4)
33573356
// Load query 1
33583357
expect(states[0]).toMatchObject({
33593358
status: 'loading',
@@ -3367,15 +3366,10 @@ describe('useQuery', () => {
33673366
// Load query 1
33683367
expect(states[2]).toMatchObject({
33693368
status: 'loading',
3370-
error: expect.any(CancelledError),
3371-
})
3372-
// State update
3373-
expect(states[3]).toMatchObject({
3374-
status: 'loading',
3375-
error: expect.any(CancelledError),
3369+
error: null,
33763370
})
33773371
// Loaded query 1
3378-
expect(states[4]).toMatchObject({
3372+
expect(states[3]).toMatchObject({
33793373
status: 'success',
33803374
error: null,
33813375
})

0 commit comments

Comments
 (0)