Skip to content

Commit d8c83b9

Browse files
authored
fix(core): make sure refetching multiple queries imperatively works offline (#5249)
* fix(core): make sure refetching multiple queries imperatively works offline * test: add another test for different networkMode * fix: always catch promises even if we don't return them because we are offline
1 parent 153ce78 commit d8c83b9

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

packages/query-core/src/queryClient.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -247,25 +247,26 @@ export class QueryClient {
247247
filters: RefetchQueryFilters = {},
248248
options?: RefetchOptions,
249249
): Promise<void> {
250+
const fetchOptions = {
251+
...options,
252+
cancelRefetch: options?.cancelRefetch ?? true,
253+
}
250254
const promises = notifyManager.batch(() =>
251255
this.#queryCache
252256
.findAll(filters)
253257
.filter((query) => !query.isDisabled())
254-
.map((query) =>
255-
query.fetch(undefined, {
256-
...options,
257-
cancelRefetch: options?.cancelRefetch ?? true,
258-
}),
259-
),
258+
.map((query) => {
259+
let promise = query.fetch(undefined, fetchOptions)
260+
if (!fetchOptions.throwOnError) {
261+
promise = promise.catch(noop)
262+
}
263+
return query.state.fetchStatus === 'paused'
264+
? Promise.resolve()
265+
: promise
266+
}),
260267
)
261268

262-
let promise = Promise.all(promises).then(noop)
263-
264-
if (!options?.throwOnError) {
265-
promise = promise.catch(noop)
266-
}
267-
268-
return promise
269+
return Promise.all(promises).then(noop)
269270
}
270271

271272
fetchQuery<

packages/query-core/src/tests/queryClient.test.tsx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { waitFor } from '@testing-library/react'
22
import '@testing-library/jest-dom'
33

4-
import { sleep, queryKey, createQueryClient } from './utils'
4+
import {
5+
sleep,
6+
queryKey,
7+
createQueryClient,
8+
mockNavigatorOnLine,
9+
} from './utils'
510
import type {
611
QueryCache,
712
QueryClient,
@@ -1020,6 +1025,33 @@ describe('queryClient', () => {
10201025
}
10211026
expect(error).toEqual('error')
10221027
})
1028+
1029+
test('should resolve Promise immediately if query is paused', async () => {
1030+
const key1 = queryKey()
1031+
const queryFn1 = vi.fn<unknown[], string>().mockReturnValue('data1')
1032+
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
1033+
const onlineMock = mockNavigatorOnLine(false)
1034+
1035+
await queryClient.refetchQueries({ queryKey: key1 })
1036+
1037+
// if we reach this point, the test succeeds because the Promise was resolved immediately
1038+
expect(queryFn1).toHaveBeenCalledTimes(1)
1039+
onlineMock.mockRestore()
1040+
})
1041+
1042+
test('should refetch if query we are offline but query networkMode is always', async () => {
1043+
const key1 = queryKey()
1044+
queryClient.setQueryDefaults(key1, { networkMode: 'always' })
1045+
const queryFn1 = vi.fn<unknown[], string>().mockReturnValue('data1')
1046+
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
1047+
const onlineMock = mockNavigatorOnLine(false)
1048+
1049+
await queryClient.refetchQueries({ queryKey: key1 })
1050+
1051+
// initial fetch + refetch (even though we are offline)
1052+
expect(queryFn1).toHaveBeenCalledTimes(2)
1053+
onlineMock.mockRestore()
1054+
})
10231055
})
10241056

10251057
describe('invalidateQueries', () => {

0 commit comments

Comments
 (0)