Manual Cache Update

You can make changes to a cache entry directly by calling api.util.updateQueryData().

Optimistic Update. ie. reflecting changes before the server responds.
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()
          /**
           * Alternatively, on failure you can invalidate the corresponding cache tags
           * to trigger a re-fetch:
           * dispatch(api.util.invalidateTags(['Post']))              <--- notice the use of another utility function
           */
        }
        // queryFulfilled.catch(patchResult.undo);    // alternative
      },
    }),
  }),
})
Pessimistic Update. ie. reflecting changes after the server responds.
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 {}
      },
    }),
  }),
})
General Update
import { api } from './api'
import { useAppDispatch } from './store/hooks'
function App() {
  const dispatch = useAppDispatch()
  function handleClick() {
    /**
     * This will update the cache data for the query corresponding to the `getPosts` endpoint,
     * when that endpoint is used with no argument (undefined).
     */
    const patchCollection = dispatch(
      api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
        draftPosts.push({ id: 1, name: 'Teddy' })
      })
    )
  }
  return <button onClick={handleClick}>Add post to cache</button>
}

If you want to merge a JSON diff/patch array with the cached data, instead of completely replacing the old entry, you can use api.util.patchQueryData() instead. const patchCollection = dispatch( api.util.updateQueryData('getPosts', undefined, (draftPosts) => { draftPosts.push({ id: 1, name: 'Teddy' }) }) ) ... dispatch( api.util.patchQueryData('getPosts', undefined, patchCollection.inversePatches) ) ... patchCollection.undo()