Skip to content

Commit

Permalink
feat(ensureQueryData): add 'revalidateIfStale' option (#6996)
Browse files Browse the repository at this point in the history
* feat(fetchQuery): add 'prefetchWhenStale' option

* Revert "feat(fetchQuery): add 'prefetchWhenStale' option"

This reverts commit 76cd6a7.

* fetch(ensureQueryData): Add revalidateIfStale option

* fetch(ensureQueryData): Add revalidateIfStale option

* fetch(ensureQueryData): Add revalidateIfStale option

* test(ensureQueryClient) implemented test for new option 'revalidateIfStale'

* Update packages/query-core/src/queryClient.ts

* feat(fetchQuery): formatted file

* Update docs/reference/QueryClient.md

* chore: prettier

---------

Co-authored-by: Dominik Dorfmeister <[email protected]>
  • Loading branch information
andredewaard and TkDodo authored Mar 13, 2024
1 parent be20804 commit e34bf4d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 5 deletions.
6 changes: 5 additions & 1 deletion docs/reference/QueryClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,11 @@ const data = await queryClient.ensureQueryData({ queryKey, queryFn })

**Options**

- The options for `ensureQueryData` are exactly the same as those of [`fetchQuery`](#queryclientfetchquery) except that `queryKey` is required.
- the same options as [`fetchQuery`](#queryclientfetchquery)
- `revalidateIfStale: boolean`
- Optional
- Defaults to `false`
- If set to `true`, stale data will be refetched in the background, but cached data will be returned immediately.

**Returns**

Expand Down
20 changes: 16 additions & 4 deletions packages/query-core/src/queryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
DefaultError,
DefaultOptions,
DefaultedQueryObserverOptions,
EnsureQueryDataOptions,
FetchInfiniteQueryOptions,
FetchQueryOptions,
InfiniteData,
Expand Down Expand Up @@ -130,13 +131,24 @@ export class QueryClient {
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
>(
options: FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
options: EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>,
): Promise<TData> {
const cachedData = this.getQueryData<TData>(options.queryKey)

return cachedData !== undefined
? Promise.resolve(cachedData)
: this.fetchQuery(options)
if (cachedData === undefined) return this.fetchQuery(options)
else {
const defaultedOptions = this.defaultQueryOptions(options)
const query = this.#queryCache.build(this, defaultedOptions)

if (
options.revalidateIfStale &&
query.isStaleByTime(defaultedOptions.staleTime)
) {
void this.prefetchQuery(defaultedOptions)
}

return Promise.resolve(cachedData)
}
}

getQueriesData<TQueryFnData = unknown>(
Expand Down
27 changes: 27 additions & 0 deletions packages/query-core/src/tests/queryClient.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,33 @@ describe('queryClient', () => {
queryClient.ensureQueryData({ queryKey: [key], queryFn }),
).resolves.toEqual('data')
})

test('should return the cached query data if the query is found and preFetchQuery in the background when revalidateIfStale is set', async () => {
const TIMEOUT = 10
const key = queryKey()
queryClient.setQueryData([key, 'id'], 'old')

const queryFn = () =>
new Promise((resolve) => {
setTimeout(() => resolve('new'), TIMEOUT)
})

await expect(
queryClient.ensureQueryData({
queryKey: [key, 'id'],
queryFn,
revalidateIfStale: true,
}),
).resolves.toEqual('old')
await sleep(TIMEOUT + 10)
await expect(
queryClient.ensureQueryData({
queryKey: [key, 'id'],
queryFn,
revalidateIfStale: true,
}),
).resolves.toEqual('new')
})
})

describe('getQueriesData', () => {
Expand Down
16 changes: 16 additions & 0 deletions packages/query-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,22 @@ export interface FetchQueryOptions<
staleTime?: number
}

export interface EnsureQueryDataOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> extends FetchQueryOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
> {
revalidateIfStale?: boolean
}

type FetchInfiniteQueryPages<TQueryFnData = unknown, TPageParam = unknown> =
| { pages?: never }
| {
Expand Down

0 comments on commit e34bf4d

Please sign in to comment.