In the RTK Query documentation https://redux-toolkit.js.org/rtk-query/usage/usage-without-react-hooks An example is given of performing a mutation without using react hooks Here is a fragment of it
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { FullUser, Post, User } from "./types";
import { cacher } from "../rtkQueryCacheUtils";
export const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: "https://jsonplaceholder.typicode.com/"
}),
// global configuration for the api
keepUnusedDataFor: 30,
tagTypes: [...cacher.defaultTags, "User"],
endpoints: (builder) => ({
getUsers: builder.query<User[], number>({
query: (count) => `users?_start=0&_end=${count}`,
providesTags: cacher.providesList("User"),
// configuration for an individual endpoint, overriding the api setting
keepUnusedDataFor: 5,
transformResponse: (response: FullUser[]) => {
const simpleUsers: User[] = response.map(({ id, name }) => ({
id,
name
}));
return simpleUsers;
}
}),
updateUser: builder.mutation<User, Partial<User> & Pick<User, "id">>({
query: ({ id, ...patch }) => ({
url: `posts/${id}`,
method: "PUT",
body: patch
}),
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
const { undo } = dispatch(
api.util.updateQueryData("getUsers", 3, (draft) => {
draft.forEach((user) => {
if (user.id === id) {
Object.assign(user, patch);
}
});
})
);
try {
await queryFulfilled;
} catch (err) {
console.log(err);
undo();
}
}
})
})
});
export const { useGetUsersQuery, useUpdateUserMutation } = api;
In string
api.util.updateQueryData("getUsers", 3, (draft) => {
queryKey equal to 3.
Is there a way to get a query Key that will match the last endpoint request "getUsers"? In order to update the cache associated with the last request
I suspect that is a typo in the example snippet and should probably be the id
variable that was destructured from the query argument passed to the updateUser
endpoint's onQueryStarted
method and is the query argument of the getUsers
endpoint, e.g. count
.
Likely corrected example using the id
to optimistically update the getUsers
endpoint cache.
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
const { undo } = dispatch(
api.util.updateQueryData("getUsers", id, (draft) => {
draft.forEach((user) => {
if (user.id === id) {
Object.assign(user, patch);
}
});
})
);
try {
await queryFulfilled;
} catch (err) {
console.log(err);
undo();
}
}
See onQueryStarted
declaration:
async function onQueryStarted(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
queryFulfilled,
getCacheEntry,
}: MutationLifecycleApi,
): Promise<void>
See also updateQueryData
:
const updateQueryData = (
endpointName: string,
args: any,
updateRecipe: (draft: Draft<CachedState>) => void,
updateProvided?: boolean,
) => ThunkAction<PatchCollection, PartialState, any, AnyAction>
interface PatchCollection {
patches: Patch[]
inversePatches: Patch[]
undo: () => void
}
The 3
, or id
, isn't the query key, it's simply the args
argument passed to the query
function.
export type query = <QueryArg>(
arg: QueryArg,
) => string | Record<string, unknown>
Note also that this isn't a mechanism used to update the last getUsers
endpoint, but to simply update the cache corresponding to the specified query arg. Order doesn't really matter, you are just updating the cache.