Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docs/src/pages/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ Its available properties and methods are:
- [`prefetchQuery`](#querycacheprefetchquery)
- [`getQueryData`](#querycachegetquerydata)
- [`setQueryData`](#querycachesetquerydata)
- [`refetchQueries`](#querycacherefetchqueries)
- [`invalidateQueries`](#querycacheinvalidatequeries)
- [`cancelQueries`](#querycachecancelqueries)
- [`removeQueries`](#querycacheremovequeries)
Expand Down Expand Up @@ -490,6 +491,52 @@ For convenience in syntax, you can also pass an updater function which receives
setQueryData(queryKey, oldData => newData)
```

## `queryCache.refetchQueries`

The `refetchQueries` method can be used to refetch queries based on certain conditions.

Examples:

```js
// refetch all queries:
await queryCache.refetchQueries()

// refetch all stale queries:
await queryCache.refetchQueries([], { stale: true })

// refetch all stale and active queries:
await queryCache.refetchQueries([], { stale: true, active: true })

// refetch all queries partially matching a query key:
await queryCache.refetchQueries(['posts'])

// refetch all queries exactly matching a query key:
await queryCache.refetchQueries(['posts', 1], { exact: true })
```

**Options**

- `queryKeyOrPredicateFn` can either be a [Query Key](#query-keys) or a `Function`
- `queryKey: QueryKey`
- If a query key is passed, queries will be filtered to those where this query key is included in the existing query's query key. This means that if you passed a query key of `'todos'`, it would match queries with the `todos`, `['todos']`, and `['todos', 5]`. See [Query Keys](./guides/queries#query-keys) for more information.
- `query => boolean`
- This predicate function will be called for every single query in the cache and be expected to return truthy for queries that are `found`.
- The `exact` option has no effect when using a function
- `exact?: boolean`
- If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed. Remember to destructure it out of the array!
- `active?: boolean`
- When set to `true` it will refetch active queries.
- When set to `false` it will refetch inactive queries.
- `stale?: boolean`
- When set to `true` it will match on stale queries.
- When set to `false` it will match on fresh queries.
- `throwOnError?: boolean`
- When set to `true`, this method will throw if any of the query refetch tasks fail.

**Returns**

This function returns a promise that will resolve when all of the queries are done being refetched. By default, it **will not** throw an error if any of those queries refetches fail, but this can be configured by setting the `throwOnError` option to `true`

## `queryCache.invalidateQueries`

The `invalidateQueries` method can be used to invalidate and refetch single or multiple queries in the cache based on their query keys or any other functionally accessible property/state of the query. By default, all matching queries are immediately marked as stale and active queries are refetched in the background.
Expand Down
84 changes: 84 additions & 0 deletions src/core/tests/queryCache.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '../../react/tests/utils'
import { QueryCache, queryCache as defaultQueryCache } from '../..'
import { isCancelledError, isError } from '../utils'
import { QueryObserver } from '../queryObserver'

describe('queryCache', () => {
test('setQueryData does not crash if query could not be found', () => {
Expand Down Expand Up @@ -230,6 +231,89 @@ describe('queryCache', () => {
)
})

test('refetchQueries should refetch all queries when no arguments are given', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn()
const queryFn2 = jest.fn()
const cache = new QueryCache()
await cache.fetchQuery(key1, queryFn1)
await cache.fetchQuery(key2, queryFn2)
await cache.refetchQueries()
cache.clear()
expect(queryFn1).toHaveBeenCalledTimes(2)
expect(queryFn2).toHaveBeenCalledTimes(2)
})

test('refetchQueries should be able to refetch all fresh queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn()
const queryFn2 = jest.fn()
const cache = new QueryCache()
await cache.fetchQuery(key1, queryFn1)
await cache.fetchQuery(key2, queryFn2)
await cache.refetchQueries([], { stale: false })
cache.clear()
expect(queryFn1).toHaveBeenCalledTimes(2)
expect(queryFn2).toHaveBeenCalledTimes(2)
})

test('refetchQueries should be able to refetch all stale queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn()
const queryFn2 = jest.fn()
const cache = new QueryCache()
await cache.fetchQuery(key1, queryFn1)
await cache.fetchQuery(key2, queryFn2)
cache.getQuery(key1)!.invalidate()
await cache.refetchQueries([], { stale: true })
cache.clear()
expect(queryFn1).toHaveBeenCalledTimes(2)
expect(queryFn2).toHaveBeenCalledTimes(1)
})

test('refetchQueries should be able to refetch all stale and active queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn()
const queryFn2 = jest.fn()
const cache = new QueryCache()
await cache.fetchQuery(key1, queryFn1)
await cache.fetchQuery(key2, queryFn2)
const query1 = cache.getQuery(key1)!
query1.invalidate()
const observer = query1.subscribe()
await cache.refetchQueries([], { active: true, stale: true })
observer.unsubscribe()
cache.clear()
expect(queryFn1).toHaveBeenCalledTimes(2)
expect(queryFn2).toHaveBeenCalledTimes(1)
})

test('refetchQueries should be able to refetch all inactive queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn()
const queryFn2 = jest.fn()
const cache = new QueryCache()
await cache.fetchQuery(key1, queryFn1)
await cache.fetchQuery(key2, queryFn2)
const query1 = cache.getQuery(key1)!
const observer = new QueryObserver({
...query1.config,
staleTime: Infinity,
})
const unsubscribe = observer.subscribe()
await cache.refetchQueries([], { active: false })
expect(queryFn1).toHaveBeenCalledTimes(1)
unsubscribe()
cache.clear()
expect(queryFn1).toHaveBeenCalledTimes(1)
expect(queryFn2).toHaveBeenCalledTimes(2)
})

test('getQueries should return queries that partially match queryKey', async () => {
const key1 = queryKey()
const key2 = queryKey()
Expand Down