A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://redux-toolkit.js.org/rtk-query/usage/manual-cache-updates below:

Manual Cache Updates | Redux Toolkit

Manual Cache Updates Overview

For most cases, in order to receive up to date data after a triggering a change in the backend, you can take advantage of cache tag invalidation to perform automated re-fetching. This will cause a query to re-fetch its data when it has been told that a mutation has occurred which would cause its data to become out of date.

We recommend using automated re-fetching as a preference over manual cache updates in most situations.

However, there are use cases when manual cache updates are necessary, such as "optimistic" or "pessimistic" updates, or modifying data as part of cache entry lifecycles.

RTK Query exports thunks for these use cases, attached to api.utils:

Since these are thunks, you can dispatch them anywhere you have access to dispatch.

Updating existing cache entries

For updates of existing cache entries, use updateQueryData.

updateQueryData is strictly intended to perform updates to existing cache entries, not create new entries. If an updateQueryData thunk action is dispatched and the endpointName + args combination that does not match any existing cache entry, the provided recipe callback will not be called, and no patches or inversePatches will be returned.

Use cases for manual update of cache entries:

Creating new cache entries or replacing existing ones

To create or replace existing cache entries, use upsertQueryData.

upsertQueryData is intended to perform replacements to existing cache entries or creation of new ones. Since upsertQueryData does not have access to the previous state of the cache entry, the update may be performed only as a replacement. In comparison, updateQueryData allows patching of the existing cache entry, but cannot create a new one.

One example use case is pessimistic updates. If the client makes an API call to create a Post, the backend could return its complete data including the id. Then we can use upsertQueryData to create a new cache entry for the getPostById(id) query, preventing an extra fetch to retrieve the item later.

Recipes Optimistic Updates

When you wish to perform an update to cache data immediately after a mutation is triggered, you can apply an optimistic update. This can be a useful pattern for when you want to give the user the impression that their changes are immediate, even while the mutation request is still in flight.

The core concepts for an optimistic update are:

tip

Where many mutations are potentially triggered in short succession causing overlapping requests, you may encounter race conditions if attempting to roll back patches using the .undo property on failures. For these scenarios, it is often simplest and safest to invalidate the tags on error instead, and re-fetch truly up-to-date data from the server.

Optimistic update mutation example (async await)

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
import type { Post } from './types'

const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
tagTypes: ['Post'],
endpoints: (build) => ({
getPost: build.query<Post, number>({
query: (id) => `post/${id}`,
providesTags: ['Post'],
}),
updatePost: build.mutation<void, Pick<Post, 'id'> & Partial<Post>>({
query: ({ id, ...patch }) => ({
url: `post/${id}`,
method: 'PATCH',
body: patch,
}),
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, patch)
}),
)
try {
await queryFulfilled
} catch {
patchResult.undo()






}
},
}),
}),
})

Optimistic update mutation example (async await)

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
tagTypes: ['Post'],
endpoints: (build) => ({
getPost: build.query({
query: (id) => `post/${id}`,
providesTags: ['Post'],
}),
updatePost: build.mutation({
query: ({ id, ...patch }) => ({
url: `post/${id}`,
method: 'PATCH',
body: patch,
}),
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, patch)
}),
)
try {
await queryFulfilled
} catch {
patchResult.undo()






}
},
}),
}),
})

or, if you prefer the slightly shorter version with .catch

-      async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
+ onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, patch)
})
)
- try {
- await queryFulfilled
- } catch {
- patchResult.undo()
- }
+ queryFulfilled.catch(patchResult.undo)
}
Example

React Optimistic Updates

Pessimistic Updates

When you wish to perform an update to cache data based on the response received from the server after a mutation is triggered, you can apply a pessimistic update. The distinction between a pessimistic update and an optimistic update is that the pessimistic update will instead wait for the response from the server prior to updating the cached data.

The core concepts for a pessimistic update are:

Pessimistic update mutation example (async await)

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
import type { Post } from './types'

const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
tagTypes: ['Post'],
endpoints: (build) => ({
getPost: build.query<Post, number>({
query: (id) => `post/${id}`,
providesTags: ['Post'],
}),
updatePost: build.mutation<Post, Pick<Post, 'id'> & Partial<Post>>({
query: ({ id, ...patch }) => ({
url: `post/${id}`,
method: 'PATCH',
body: patch,
}),
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
try {
const { data: updatedPost } = await queryFulfilled
const patchResult = dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, updatedPost)
}),
)
} catch {}
},
}),
createPost: build.mutation<Post, Pick<Post, 'id'> & Partial<Post>>({
query: ({ id, ...body }) => ({
url: `post/${id}`,
method: 'POST',
body,
}),
async onQueryStarted({ id }, { dispatch, queryFulfilled }) {
try {
const { data: createdPost } = await queryFulfilled
const patchResult = dispatch(
api.util.upsertQueryData('getPost', id, createdPost),
)
} catch {}
},
}),
}),
})

Pessimistic update mutation example (async await)

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
tagTypes: ['Post'],
endpoints: (build) => ({
getPost: build.query({
query: (id) => `post/${id}`,
providesTags: ['Post'],
}),
updatePost: build.mutation({
query: ({ id, ...patch }) => ({
url: `post/${id}`,
method: 'PATCH',
body: patch,
}),
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
try {
const { data: updatedPost } = await queryFulfilled
const patchResult = dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, updatedPost)
}),
)
} catch {}
},
}),
createPost: build.mutation({
query: ({ id, ...body }) => ({
url: `post/${id}`,
method: 'POST',
body,
}),
async onQueryStarted({ id }, { dispatch, queryFulfilled }) {
try {
const { data: createdPost } = await queryFulfilled
const patchResult = dispatch(
api.util.upsertQueryData('getPost', id, createdPost),
)
} catch {}
},
}),
}),
})
General Updates

If you find yourself wanting to update cache data elsewhere in your application, you can do so anywhere you have access to the store.dispatch method, including within React components via the useDispatch hook (or a typed version such as useAppDispatch for typescript users).

info

You should generally avoid manually updating the cache outside of the onQueryStarted callback for a mutation without a good reason, as RTK Query is intended to be used by considering your cached data as a reflection of the server-side state.

General manual cache update example

import { api } from './api'
import { useAppDispatch } from './store/hooks'

function App() {
const dispatch = useAppDispatch()

function handleClick() {




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

return <button onClick={handleClick}>Add post to cache</button>
}

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4