Skip to content

Commit

Permalink
📝 Tweak cache management utils page (#1113)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shrugsy authored Jun 2, 2021
1 parent ca5bf83 commit b1e4438
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 7 deletions.
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

0 comments on commit b1e4438

Please sign in to comment.