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
25 changes: 25 additions & 0 deletions docs/src/pages/reference/QueryClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Its available methods are:
- [`refetchQueries`](#queryclientrefetchqueries)
- [`cancelQueries`](#queryclientcancelqueries)
- [`removeQueries`](#queryclientremovequeries)
- [`resetQueries`](#queryclientresetqueries)
- [`isFetching`](#queryclientisfetching)
- [`getDefaultOptions`](#queryclientsetdefaultoptions)
- [`setDefaultOptions`](#queryclientgetdefaultoptions)
Expand Down Expand Up @@ -274,6 +275,30 @@ queryClient.removeQueries(queryKey, { exact: true })

This method does not return anything

## `queryClient.resetQueries`

The `resetQueries` method can be used to reset queries in the cache to their
initial state based on their query keys or any other functionally accessible
property/state of the query.

This will notify subscribers — unlike `clear`, which removes all
subscribers — and reset the query to its pre-loaded state — unlike
`invalidateQueries`. If a query has `initialData`, the query's data will be
reset to that.

```js
queryClient.resetQueries(queryKey, { exact: true })
```

**Options**

- `queryKey?: QueryKey`: [Query Keys](../guides/query-keys)
- `filters?: QueryFilters`: [Query Filters](../guides/query-filters)

**Returns**

This method does not return anything

## `queryClient.isFetching`

This `isFetching` method returns an `integer` representing how many queries, if any, in the cache are currently fetching (including background-fetching, loading new pages, or loading more infinite query results)
Expand Down
9 changes: 8 additions & 1 deletion src/core/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export class Query<TData = unknown, TError = unknown, TQueryFnData = TData> {
queryKey: QueryKey
queryHash: string
options!: QueryOptions<TData, TError, TQueryFnData>
initialState: QueryState<TData, TError>
state: QueryState<TData, TError>
cacheTime!: number

Expand All @@ -141,7 +142,8 @@ export class Query<TData = unknown, TError = unknown, TQueryFnData = TData> {
this.cache = config.cache
this.queryKey = config.queryKey
this.queryHash = config.queryHash
this.state = config.state || this.getDefaultState(this.options)
this.initialState = config.state || this.getDefaultState(this.options)
this.state = this.initialState
this.scheduleGc()
}

Expand Down Expand Up @@ -220,6 +222,11 @@ export class Query<TData = unknown, TError = unknown, TQueryFnData = TData> {
this.cancel()
}

reset(): void {
this.destroy()
this.setState(this.initialState)
}

isActive(): boolean {
return this.observers.some(observer => observer.options.enabled !== false)
}
Expand Down
12 changes: 12 additions & 0 deletions src/core/queryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,18 @@ export class QueryClient {
})
}

resetQueries(filters?: QueryFilters): void
resetQueries(queryKey?: QueryKey, filters?: QueryFilters): void
resetQueries(arg1?: QueryKey | QueryFilters, arg2?: QueryFilters): void {
const [filters] = parseFilterArgs(arg1, arg2)
const queryCache = this.queryCache
notifyManager.batch(() => {
queryCache.findAll(filters).forEach(query => {
query.reset()
})
})
}

cancelQueries(filters?: QueryFilters, options?: CancelOptions): Promise<void>
cancelQueries(
queryKey?: QueryKey,
Expand Down
50 changes: 50 additions & 0 deletions src/core/tests/queryCache.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,56 @@ describe('queryCache', () => {
expect(queryFn2).toHaveBeenCalledTimes(1)
})

test('should notify listeners when a query is reset', async () => {
const key = queryKey()

const callback = jest.fn()

await queryClient.prefetchQuery(key, () => 'data')

queryCache.subscribe(callback)

queryClient.resetQueries(key)

expect(callback).toHaveBeenCalled()
})

test('resetQueries should reset query', async () => {
const key = queryKey()

await queryClient.prefetchQuery(key, () => 'data')

let state = queryClient.getQueryState(key)
expect(state?.data).toEqual('data')
expect(state?.status).toEqual('success')

queryClient.resetQueries(key)

state = queryClient.getQueryState(key)

expect(state).toBeTruthy()
expect(state?.data).toBeUndefined()
expect(state?.status).toEqual('idle')
})

test('resetQueries should reset query data to initial data if set', async () => {
const key = queryKey()

await queryClient.prefetchQuery(key, () => 'data', {
initialData: 'initial',
})

let state = queryClient.getQueryState(key)
expect(state?.data).toEqual('data')

queryClient.resetQueries(key)

state = queryClient.getQueryState(key)

expect(state).toBeTruthy()
expect(state?.data).toEqual('initial')
})

test('find should filter correctly', async () => {
const key = queryKey()
const testCache = new QueryCache()
Expand Down