Skip to content

Commit c7e342a

Browse files
authored
fix: useInfinityQuery fetchMore should not throw (#1004)
1 parent 3d967bf commit c7e342a

File tree

5 files changed

+59
-18
lines changed

5 files changed

+59
-18
lines changed

src/core/query.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ export class Query<TResult, TError> {
296296
}
297297
}
298298

299-
async fetchMore(
299+
fetchMore(
300300
fetchMoreVariable?: unknown,
301301
options?: FetchMoreOptions,
302302
config?: ResolvedQueryConfig<TResult, TError>
@@ -380,7 +380,7 @@ export class Query<TResult, TError> {
380380
return this.promise
381381
}
382382

383-
private async startFetch(
383+
private startFetch(
384384
config: ResolvedQueryConfig<TResult, TError>,
385385
params: unknown[],
386386
_options?: FetchOptions
@@ -397,7 +397,7 @@ export class Query<TResult, TError> {
397397
return this.tryFetchData(config, fetchData)
398398
}
399399

400-
private async startInfiniteFetch(
400+
private startInfiniteFetch(
401401
config: ResolvedQueryConfig<TResult, TError>,
402402
params: unknown[],
403403
options?: FetchOptions
@@ -455,7 +455,7 @@ export class Query<TResult, TError> {
455455
return this.tryFetchData(config, fetchData)
456456
}
457457

458-
private async tryFetchData<T>(
458+
private tryFetchData<T>(
459459
config: ResolvedQueryConfig<TResult, TError>,
460460
fn: QueryFunction<T>
461461
): Promise<T> {

src/core/queryObserver.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import {
22
getStatusProps,
3-
isServer,
43
isDocumentVisible,
4+
isServer,
55
isValidTimeout,
6+
noop,
67
} from './utils'
78
import type { QueryResult, ResolvedQueryConfig } from './types'
89
import type { Query, Action, FetchMoreOptions, RefetchOptions } from './query'
@@ -108,23 +109,21 @@ export class QueryObserver<TResult, TError> {
108109
return this.currentQuery.clear()
109110
}
110111

111-
async refetch(options?: RefetchOptions): Promise<TResult | undefined> {
112+
refetch(options?: RefetchOptions): Promise<TResult | undefined> {
112113
return this.currentQuery.refetch(options, this.config)
113114
}
114115

115-
async fetchMore(
116+
fetchMore(
116117
fetchMoreVariable?: unknown,
117118
options?: FetchMoreOptions
118119
): Promise<TResult | undefined> {
119-
return this.currentQuery.fetchMore(fetchMoreVariable, options, this.config)
120+
return this.currentQuery
121+
.fetchMore(fetchMoreVariable, options, this.config)
122+
.catch(noop)
120123
}
121124

122-
async fetch(): Promise<TResult | undefined> {
123-
try {
124-
return await this.currentQuery.fetch(undefined, this.config)
125-
} catch {
126-
// ignore
127-
}
125+
fetch(): Promise<TResult | undefined> {
126+
return this.currentQuery.fetch(undefined, this.config).catch(noop)
128127
}
129128

130129
private optionalFetch(): void {

src/core/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ export function uid(): number {
3636

3737
export const isServer = typeof window === 'undefined'
3838

39-
export function noop(): void {
40-
return void 0
39+
export function noop(): undefined {
40+
return undefined
4141
}
4242

4343
export let Console: ConsoleObject = console || {

src/react/tests/useInfiniteQuery.test.tsx

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { render, waitFor, fireEvent } from '@testing-library/react'
22
import * as React from 'react'
33

4-
import { sleep, queryKey, waitForMs } from './utils'
4+
import { sleep, queryKey, waitForMs, mockConsoleError } from './utils'
55
import { useInfiniteQuery, useQueryCache } from '..'
66
import { InfiniteQueryResult } from '../../core'
77

@@ -112,6 +112,48 @@ describe('useInfiniteQuery', () => {
112112
})
113113
})
114114

115+
it('should not throw when fetchMore returns an error', async () => {
116+
const consoleMock = mockConsoleError()
117+
const key = queryKey()
118+
let noThrow: boolean
119+
120+
function Page() {
121+
const start = 1
122+
const state = useInfiniteQuery(
123+
key,
124+
async (_key, page: number = start) => {
125+
if (page === 2) {
126+
throw new Error('error')
127+
}
128+
return page
129+
},
130+
{
131+
retry: 1,
132+
retryDelay: 10,
133+
getFetchMore: (lastPage, _pages) => lastPage + 1,
134+
}
135+
)
136+
137+
const { fetchMore } = state
138+
139+
React.useEffect(() => {
140+
setTimeout(async () => {
141+
try {
142+
await fetchMore()
143+
noThrow = true
144+
} catch (error) {}
145+
}, 20)
146+
}, [fetchMore])
147+
148+
return null
149+
}
150+
151+
render(<Page />)
152+
153+
await waitFor(() => expect(noThrow).toBe(true))
154+
consoleMock.mockRestore()
155+
})
156+
115157
it('should keep the previous data when keepPreviousData is set', async () => {
116158
const key = queryKey()
117159
const states: InfiniteQueryResult<string>[] = []

src/react/useBaseQuery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getResolvedQueryConfig } from '../core/config'
55
import { QueryObserver } from '../core/queryObserver'
66
import { QueryResultBase, QueryKey, QueryConfig } from '../core/types'
77
import { useErrorResetBoundary } from './ReactQueryErrorResetBoundary'
8-
import { useQueryCache } from '.'
8+
import { useQueryCache } from './ReactQueryCacheProvider'
99
import { useContextConfig } from './ReactQueryConfigProvider'
1010

1111
export function useBaseQuery<TResult, TError>(

0 commit comments

Comments
 (0)