Skip to content

Commit f9f9cce

Browse files
authored
fix: queries should not end up in an error state when a component unmounts (TanStack#1781)
1 parent 4a821b0 commit f9f9cce

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
}
@@ -378,6 +379,9 @@ export class Query<
378379
this.options.behavior?.onFetch(context)
379380
}
380381

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

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

553541
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,
@@ -3421,7 +3420,7 @@ describe('useQuery', () => {
34213420
renderWithClient(queryClient, <Page />)
34223421

34233422
await sleep(100)
3424-
expect(states.length).toBe(5)
3423+
expect(states.length).toBe(4)
34253424
// Load query 1
34263425
expect(states[0]).toMatchObject({
34273426
status: 'loading',
@@ -3435,15 +3434,10 @@ describe('useQuery', () => {
34353434
// Load query 1
34363435
expect(states[2]).toMatchObject({
34373436
status: 'loading',
3438-
error: expect.any(CancelledError),
3439-
})
3440-
// State update
3441-
expect(states[3]).toMatchObject({
3442-
status: 'loading',
3443-
error: expect.any(CancelledError),
3437+
error: null,
34443438
})
34453439
// Loaded query 1
3446-
expect(states[4]).toMatchObject({
3440+
expect(states[3]).toMatchObject({
34473441
status: 'success',
34483442
error: null,
34493443
})

0 commit comments

Comments
 (0)