Skip to content

Commit

Permalink
fix(core): make sure refetching multiple queries imperatively works o…
Browse files Browse the repository at this point in the history
…ffline (#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
  • Loading branch information
TkDodo authored May 1, 2023
1 parent 153ce78 commit d8c83b9
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
27 changes: 14 additions & 13 deletions packages/query-core/src/queryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,25 +247,26 @@ export class QueryClient {
filters: RefetchQueryFilters = {},
options?: RefetchOptions,
): Promise<void> {
const fetchOptions = {
...options,
cancelRefetch: options?.cancelRefetch ?? true,
}
const promises = notifyManager.batch(() =>
this.#queryCache
.findAll(filters)
.filter((query) => !query.isDisabled())
.map((query) =>
query.fetch(undefined, {
...options,
cancelRefetch: options?.cancelRefetch ?? true,
}),
),
.map((query) => {
let promise = query.fetch(undefined, fetchOptions)
if (!fetchOptions.throwOnError) {
promise = promise.catch(noop)
}
return query.state.fetchStatus === 'paused'
? Promise.resolve()
: promise
}),
)

let promise = Promise.all(promises).then(noop)

if (!options?.throwOnError) {
promise = promise.catch(noop)
}

return promise
return Promise.all(promises).then(noop)
}

fetchQuery<
Expand Down
34 changes: 33 additions & 1 deletion packages/query-core/src/tests/queryClient.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'

import { sleep, queryKey, createQueryClient } from './utils'
import {
sleep,
queryKey,
createQueryClient,
mockNavigatorOnLine,
} from './utils'
import type {
QueryCache,
QueryClient,
Expand Down Expand Up @@ -1020,6 +1025,33 @@ describe('queryClient', () => {
}
expect(error).toEqual('error')
})

test('should resolve Promise immediately if query is paused', async () => {
const key1 = queryKey()
const queryFn1 = vi.fn<unknown[], string>().mockReturnValue('data1')
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
const onlineMock = mockNavigatorOnLine(false)

await queryClient.refetchQueries({ queryKey: key1 })

// if we reach this point, the test succeeds because the Promise was resolved immediately
expect(queryFn1).toHaveBeenCalledTimes(1)
onlineMock.mockRestore()
})

test('should refetch if query we are offline but query networkMode is always', async () => {
const key1 = queryKey()
queryClient.setQueryDefaults(key1, { networkMode: 'always' })
const queryFn1 = vi.fn<unknown[], string>().mockReturnValue('data1')
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
const onlineMock = mockNavigatorOnLine(false)

await queryClient.refetchQueries({ queryKey: key1 })

// initial fetch + refetch (even though we are offline)
expect(queryFn1).toHaveBeenCalledTimes(2)
onlineMock.mockRestore()
})
})

describe('invalidateQueries', () => {
Expand Down

0 comments on commit d8c83b9

Please sign in to comment.