Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📝 Tweak cache management utils page #1113

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
197 changes: 197 additions & 0 deletions docs/rtk-query/api/created-api/cache-management-utils.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
---
id: cache-management-utils
title: 'API Slices: Cache Management'
sidebar_label: Cache Management Utils
hide_title: true
---

 

# API Slices: Cache Management Utilities

The API slice object includes cache management utilities that are used for implementing [optimistic updates](../../usage/optimistic-updates.mdx). These are included in a `util` field inside the slice object.

### `updateQueryData`

#### Signature

```ts no-transpile
const updateQueryData = (
endpointName: string,
args: any,
updateRecipe: (draft: Draft<CachedState>) => void
) => ThunkAction<PatchCollection, PartialState, any, AnyAction>;

interface PatchCollection {
patches: Patch[];
inversePatches: Patch[];
undo: () => void;
}
```

- **Parameters**
- `endpointName`: a string matching an existing endpoint name
- `args`: a cache key, used to determine which cached dataset needs to be updated
- `updateRecipe`: an Immer `produce` callback that can apply changes to the cached state

#### Description

A Redux thunk action creator that, when dispatched, creates and applies a set of JSON diff/patch objects to the current state. This immediately updates the Redux state with those changes.

The thunk action creator accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), any relevant query arguments, and a callback function. The callback receives an Immer-wrapped `draft` of the current state, and may modify the draft to match the expected results after the mutation completes successfully.

The thunk returns an object containing `{patches: Patch[], inversePatches: Patch[], undo: () => void}`. The `patches` and `inversePatches` are generated using Immer's [`produceWithPatches` method](https://immerjs.github.io/immer/patches).

This is typically used as the first step in implementing optimistic updates. The generated `inversePatches` can be used to revert the updates by calling `dispatch(patchQueryData(endpointName, args, inversePatches))`. Alternatively, the `undo` method can be called directly to achieve the same effect.

#### Example

```ts no-transpile
const patchCollection = dispatch(
api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
draftPosts.push({ id: 1, name: 'Teddy' })
})
)
```

### `patchQueryData`

#### Signature

```ts no-transpile
const patchQueryData = (
endpointName: string,
args: any
patches: Patch[]
) => ThunkAction<void, PartialState, any, AnyAction>;
```

- **Parameters**
- `endpointName`: a string matching an existing endpoint name
- `args`: a cache key, used to determine which cached dataset needs to be updated
- `patches`: an array of patches (or inverse patches) to apply to cached state. These would typically be obtained from the result of dispatching [`updateQueryData`](#updatequerydata)

#### Description

A Redux thunk action creator that applies a JSON diff/patch array to the cached data for a given query result. This immediately updates the Redux state with those changes.

The thunk action creator accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), any relevant query arguments, and a JSON diff/patch array as produced by Immer's `produceWithPatches`.

This is typically used as the second step in implementing optimistic updates. If a request fails, the optimistically-applied changes can be reverted by dispatching `patchQueryData` with the `inversePatches` that were generated by `updateQueryData` earlier.

In cases where it is desired to simply revert the previous changes, it may be preferable to call the `undo` method returned from dispatching `updateQueryData` instead.

#### Example

```ts no-transpile
const patchCollection = dispatch(
api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
draftPosts.push({ id: 1, name: 'Teddy' })
})
)

// later
dispatch(
api.util.patchQueryData('getPosts', undefined, patchCollection.inversePatches)
)

// or
patchCollection.undo()
```

### `prefetch`

#### Signature

```ts no-transpile
type PrefetchOptions = { ifOlderThan?: false | number } | { force?: boolean };

const prefetch = (
endpointName: string,
arg: any,
options: PrefetchOptions
) => ThunkAction<void, any, any, AnyAction>;
```

- **Parameters**

- `endpointName`: a string matching an existing endpoint name
- `args`: a cache key, used to determine which cached dataset needs to be updated
- `options`: options to determine whether the request should be sent for a given situation:
- `ifOlderThan`: if specified, only runs the query if the difference between `new Date()` and the last`fulfilledTimeStamp` is greater than the given value (in seconds)
- `force`: if `true`, it will ignore the `ifOlderThan` value if it is set and the query will be run even if it exists in the cache.

#### Description

A Redux thunk action creator that can be used to manually trigger pre-fetching of data.

The thunk action creator accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), any relevant query arguments, and a set of options used to determine if the data actually should be re-fetched based on cache staleness.

React Hooks users will most likely never need to use this directly, as the `usePrefetch` hook will dispatch the thunk action creator result internally as needed when you call the prefetching function supplied by the hook.

#### Example

```ts no-transpile
dispatch(api.util.prefetch('getPosts', undefined, { force: true }))
```

### `invalidateTags`

#### Signature

```ts no-transpile
const invalidateTags = (
tags: Array<TagTypes | FullTagDescription<TagTypes>>
) => ({
type: string,
payload: tags,
})
```

- **Parameters**
- `tags`: an array of tags to be invalidated, where the provided `TagType` is one of the strings provided to the [`tagTypes`](../createApi.mdx#tagtypes) property of the api. e.g.
- `[TagType]`
- `[{ type: TagType }]`
- `[{ type: TagType, id: number | string }]`

#### Description

A Redux action creator that can be used to manually invalidate cache tags for [automated re-fetching](../../usage/automated-refetching.mdx).

The action creator accepts one argument: the cache tags to be invalidated. It returns an action with those tags as a payload, and the corresponding `invalidateTags` action type for the api.

Dispatching the result of this action creator will [invalidate](../../usage/automated-refetching.mdx#invalidating-cache-data) the given tags, causing queries to automatically re-fetch if they are subscribed to cache data that [provides](../../usage/automated-refetching.mdx#providing-cache-data) the corresponding tags.

#### Example

```ts no-transpile
dispatch(api.util.invalidateTags(['Post']))
dispatch(api.util.invalidateTags([{ type: 'Post', id: 1 }]))
dispatch(
api.util.invalidateTags([
{ type: 'Post', id: 1 },
{ type: 'Post', id: 'LIST' },
])
)
```

### `resetApiState`

#### Signature

```ts no-transpile
const resetApiState = () => ({
type: string,
payload: undefined,
})
```

#### Description

A Redux action creator that can be dispatched to manually reset the api state completely. This will immediately remove all existing cache entries, and all queries will be considered 'uninitialized'.

#### Example

```ts no-transpile
dispatch(api.util.resetApiState())
```
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"reducer",
"slice",
"immer",
"immutable"
"immutable",
"redux-toolkit"
],
"publishConfig": {
"access": "public"
Expand Down
88 changes: 83 additions & 5 deletions src/query/core/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,41 @@ declare module '../apiTypes' {
*/
util: {
/**
* TODO
* A Redux thunk that can be used to manually trigger pre-fetching of data.
*
* The thunk accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), any relevant query arguments, and a set of options used to determine if the data actually should be re-fetched based on cache staleness.
*
* React Hooks users will most likely never need to use this directly, as the `usePrefetch` hook will dispatch this thunk internally as needed when you call the prefetching function supplied by the hook.
*
* @example
*
* ```ts no-transpile
* dispatch(api.util.prefetch('getPosts', undefined, { force: true }))
* ```
*/
prefetch<EndpointName extends QueryKeys<Definitions>>(
endpointName: EndpointName,
arg: QueryArgFrom<Definitions[EndpointName]>,
options: PrefetchOptions
): ThunkAction<void, any, any, AnyAction>
/**
* TODO
* A Redux thunk action creator that, when dispatched, creates and applies a set of JSON diff/patch objects to the current state. This immediately updates the Redux state with those changes.
*
* The thunk action creator accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), any relevant query arguments, and a callback function. The callback receives an Immer-wrapped `draft` of the current state, and may modify the draft to match the expected results after the mutation completes successfully.
*
* The thunk returns an object containing `{patches: Patch[], inversePatches: Patch[], undo: () => void}`. The `patches` and `inversePatches` are generated using Immer's [`produceWithPatches` method](https://immerjs.github.io/immer/patches).
*
* This is typically used as the first step in implementing optimistic updates. The generated `inversePatches` can be used to revert the updates by calling `dispatch(patchQueryData(endpointName, args, inversePatches))`. Alternatively, the `undo` method can be called directly to achieve the same effect.
*
* @example
*
* ```ts
* const patchCollection = dispatch(
* api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
* draftPosts.push({ id: 1, name: 'Teddy' })
* })
* )
* ```
*/
updateQueryData: UpdateQueryDataThunk<
Definitions,
Expand All @@ -145,7 +171,30 @@ declare module '../apiTypes' {
RootState<Definitions, string, ReducerPath>
>
/**
* TODO
* A Redux thunk that applies a JSON diff/patch array to the cached data for a given query result. This immediately updates the Redux state with those changes.
*
* The thunk accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), any relevant query arguments, and a JSON diff/patch array as produced by Immer's `produceWithPatches`.
*
* This is typically used as the second step in implementing optimistic updates. If a request fails, the optimistically-applied changes can be reverted by dispatching `patchQueryData` with the `inversePatches` that were generated by `updateQueryData` earlier.
*
* In cases where it is desired to simply revert the previous changes, it may be preferable to call the `undo` method returned from dispatching `updateQueryData` instead.
*
* @example
* ```ts
* const patchCollection = dispatch(
* api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
* draftPosts.push({ id: 1, name: 'Teddy' })
* })
* )
*
* // later
* dispatch(
* api.util.patchQueryData('getPosts', undefined, patchCollection.inversePatches)
* )
*
* // or
* patchCollection.undo()
* ```
*/
patchQueryData: PatchQueryDataThunk<
Definitions,
Expand All @@ -157,11 +206,40 @@ declare module '../apiTypes' {
RootState<Definitions, string, ReducerPath>
>
/**
* TODO
* A Redux action creator that can be dispatched to manually reset the api state completely. This will immediately remove all existing cache entries, and all queries will be considered 'uninitialized'.
*
* @example
*
* ```ts
* dispatch(api.util.resetApiState())
* ```
*/
resetApiState: SliceActions['resetApiState']
/**
* TODO
* A Redux action creator that can be used to manually invalidate cache tags for [automated re-fetching](../../usage/automated-refetching.mdx).
*
* The action creator accepts one argument: the cache tags to be invalidated. It returns an action with those tags as a payload, and the corresponding `invalidateTags` action type for the api.
*
* Dispatching the result of this action creator will [invalidate](../../usage/automated-refetching.mdx#invalidating-cache-data) the given tags, causing queries to automatically re-fetch if they are subscribed to cache data that [provides](../../usage/automated-refetching.mdx#providing-cache-data) the corresponding tags.
*
* The array of tags provided to the action creator should be in one of the following formats, where `TagType` is equal to a string provided to the [`tagTypes`](../createApi.mdx#tagtypes) property of the api:
*
* - `[TagType]`
* - `[{ type: TagType }]`
* - `[{ type: TagType, id: number | string }]`
*
* @example
*
* ```ts
* dispatch(api.util.invalidateTags(['Post']))
* dispatch(api.util.invalidateTags([{ type: 'Post', id: 1 }]))
* dispatch(
* api.util.invalidateTags([
* { type: 'Post', id: 1 },
* { type: 'Post', id: 'LIST' },
* ])
* )
* ```
*/
invalidateTags: ActionCreatorWithPayload<
Array<TagTypes | FullTagDescription<TagTypes>>,
Expand Down
2 changes: 1 addition & 1 deletion website/sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
"rtk-query/api/created-api/redux-integration",
"rtk-query/api/created-api/endpoints",
"rtk-query/api/created-api/code-splitting",
"rtk-query/api/created-api/cache-management",
"rtk-query/api/created-api/cache-management-utils",
"rtk-query/api/created-api/hooks"
]
}
Expand Down