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/mutations below:

Mutations | Redux Toolkit

Mutations Overview

Mutations are used to send data updates to the server and apply the changes to the local cache. Mutations can also invalidate cached data and force re-fetches.

Defining Mutation Endpoints

Mutation endpoints are defined by returning an object inside the endpoints section of createApi, and defining the fields using the build.mutation() method.

Mutation endpoints should define either a query callback that constructs the URL (including any URL query params), or a queryFn callback that may do arbitrary async logic and return a result. The query callback may also return an object containing the URL, the HTTP method to use and a request body.

If the query callback needs additional data to generate the URL, it should be written to take a single argument. If you need to pass in multiple parameters, pass them formatted as a single "options object".

Mutation endpoints may also modify the response contents before the result is cached, define "tags" to identify cache invalidation, and provide cache entry lifecycle callbacks to run additional logic as cache entries are added and removed.

When used with TypeScript, you should supply generics for the return type and the expected query argument: build.mutation<ReturnType, ArgType>. If there is no argument, use void for the arg type instead.

Example of all mutation endpoint options

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

const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
tagTypes: ['Post'],
endpoints: (build) => ({

updatePost: build.mutation<Post, Partial<Post> & Pick<Post, 'id'>>({

query: ({ id, ...patch }) => ({
url: `post/${id}`,
method: 'PATCH',
body: patch,
}),

transformResponse: (response: { data: Post }, meta, arg) => response.data,

transformErrorResponse: (
response: { status: string | number },
meta,
arg,
) => response.status,
invalidatesTags: ['Post'],


async onQueryStarted(
arg,
{ dispatch, getState, queryFulfilled, requestId, extra, getCacheEntry },
) {},

async onCacheEntryAdded(
arg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
},
) {},
}),
}),
})

Example of all mutation endpoint options

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

const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: '/',
}),
tagTypes: ['Post'],
endpoints: (build) => ({

updatePost: build.mutation({

query: ({ id, ...patch }) => ({
url: `post/${id}`,
method: 'PATCH',
body: patch,
}),

transformResponse: (response, meta, arg) => response.data,

transformErrorResponse: (response, meta, arg) => response.status,
invalidatesTags: ['Post'],


async onQueryStarted(
arg,
{ dispatch, getState, queryFulfilled, requestId, extra, getCacheEntry },
) {},

async onCacheEntryAdded(
arg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
},
) {},
}),
}),
})
Performing Mutations with React Hooks Mutation Hook Behavior

Unlike useQuery, useMutation returns a tuple. The first item in the tuple is the "trigger" function and the second element contains an object with status, error, and data.

Unlike the useQuery hook, the useMutation hook doesn't execute automatically. To run a mutation you have to call the trigger function returned as the first tuple value from the hook.

See useMutation for the hook signature and additional details.

Frequently Used Mutation Hook Return Values

The useMutation hook returns a tuple containing a "mutation trigger" function, as well as an object containing properties about the "mutation result".

The "mutation trigger" is a function that when called, will fire off the mutation request for that endpoint. Calling the "mutation trigger" returns a promise with an unwrap property, which can be called to unwrap the mutation call and provide the raw response/error. This can be useful if you wish to determine whether the mutation succeeds/fails inline at the call-site.

The "mutation result" is an object containing properties such as the latest data for the mutation request, as well as status booleans for the current request lifecycle state.

Below are some of the most frequently used properties on the "mutation result" object. Refer to useMutation for an extensive list of all returned properties.

note

With RTK Query, a mutation does not contain a semantic distinction between 'loading' and 'fetching' in the way that a query does. For a mutation, subsequent calls are not assumed to be necessarily related, so a mutation is either 'loading' or 'not loading', with no concept of 're-fetching'.

By default, separate instances of a useMutation hook are not inherently related to each other. Triggering one instance will not affect the result for a separate instance. This applies regardless of whether the hooks are called within the same component, or different components.

export const ComponentOne = () => {


const [updatePost, result] = useUpdatePostMutation()

return <div>...</div>
}

export const ComponentTwo = () => {
const [updatePost, result] = useUpdatePostMutation()

return <div>...</div>
}

RTK Query provides an option to share results across mutation hook instances using the fixedCacheKey option. Any useMutation hooks with the same fixedCacheKey string will share results between each other when any of the trigger functions are called. This should be a unique string shared between each mutation hook instance you wish to share results.

export const ComponentOne = () => {


const [updatePost, result] = useUpdatePostMutation({
fixedCacheKey: 'shared-update-post',
})

return <div>...</div>
}

export const ComponentTwo = () => {
const [updatePost, result] = useUpdatePostMutation({
fixedCacheKey: 'shared-update-post',
})

return <div>...</div>
}

note

When using fixedCacheKey, the originalArgs property is not able to be shared and will always be undefined.

Standard Mutation Example

This is a modified version of the complete example you can see at the bottom of the page to highlight the updatePost mutation. In this scenario, a post is fetched with useQuery, and then an EditablePostName component is rendered that allows us to edit the name of the post.

src/features/posts/PostDetail.tsx

export const PostDetail = () => {
const { id } = useParams<{ id: any }>()

const { data: post } = useGetPostQuery(id)

const [
updatePost,
{ isLoading: isUpdating },
] = useUpdatePostMutation()

return (
<Box p={4}>
<EditablePostName
name={post.name}
onUpdate={(name) => {




return (

updatePost({ id, name })
)
}}
isLoading={isUpdating}
/>
</Box>
)
}
Advanced Mutations with Revalidation

In the real world, it's very common that a developer would want to resync their local data cache with the server after performing a mutation (aka "revalidation"). RTK Query takes a more centralized approach to this and requires you to configure the invalidation behavior in your API service definition. See Advanced Invalidation with abstract tag IDs for details on advanced invalidation handling with RTK Query.

Revalidation Example

This is an example of a CRUD service for Posts. This implements the Selectively invalidating lists strategy and will most likely serve as a good foundation for real applications.

src/app/services/posts.ts


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

export interface Post {
id: number
name: string
}

type PostsResponse = Post[]

export const postApi = createApi({
reducerPath: 'postsApi',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',



providesTags: (result) =>

result
?
[
...result.map(({ id }) => ({ type: 'Posts', id }) as const),
{ type: 'Posts', id: 'LIST' },
]
:
[{ type: 'Posts', id: 'LIST' }],
}),
addPost: build.mutation<Post, Partial<Post>>({
query(body) {
return {
url: `post`,
method: 'POST',
body,
}
},


invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
}),
getPost: build.query<Post, number>({
query: (id) => `post/${id}`,
providesTags: (result, error, id) => [{ type: 'Posts', id }],
}),
updatePost: build.mutation<Post, Partial<Post>>({
query(data) {
const { id, ...body } = data
return {
url: `post/${id}`,
method: 'PUT',
body,
}
},


invalidatesTags: (result, error, { id }) => [{ type: 'Posts', id }],
}),
deletePost: build.mutation<{ success: boolean; id: number }, number>({
query(id) {
return {
url: `post/${id}`,
method: 'DELETE',
}
},

invalidatesTags: (result, error, id) => [{ type: 'Posts', id }],
}),
}),
})

export const {
useGetPostsQuery,
useAddPostMutation,
useGetPostQuery,
useUpdatePostMutation,
useDeletePostMutation,
} = postApi

src/app/services/posts.js


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

export const postApi = createApi({
reducerPath: 'postsApi',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query({
query: () => 'posts',



providesTags: (result) =>

result
?
[
...result.map(({ id }) => ({ type: 'Posts', id })),
{ type: 'Posts', id: 'LIST' },
]
:
[{ type: 'Posts', id: 'LIST' }],
}),
addPost: build.mutation({
query(body) {
return {
url: `post`,
method: 'POST',
body,
}
},


invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
}),
getPost: build.query({
query: (id) => `post/${id}`,
providesTags: (result, error, id) => [{ type: 'Posts', id }],
}),
updatePost: build.mutation({
query(data) {
const { id, ...body } = data
return {
url: `post/${id}`,
method: 'PUT',
body,
}
},


invalidatesTags: (result, error, { id }) => [{ type: 'Posts', id }],
}),
deletePost: build.mutation({
query(id) {
return {
url: `post/${id}`,
method: 'DELETE',
}
},

invalidatesTags: (result, error, id) => [{ type: 'Posts', id }],
}),
}),
})

export const {
useGetPostsQuery,
useAddPostMutation,
useGetPostQuery,
useUpdatePostMutation,
useDeletePostMutation,
} = postApi
Runtime Validation using Schemas

Endpoints can use any Standard Schema compliant library for runtime validation of query args, responses, and errors. See API reference for full list of available schemas.

When used with TypeScript, schemas can also be used to infer the type of that value instead of having to declare it.

Most commonly, you'll want to use responseSchema to validate the response from the server (or rawResponseSchema when using transformResponse).

Using responseSchema

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import * as v from 'valibot'

const postSchema = v.object({
id: v.number(),
name: v.string(),
published_at: v.string(),
})
type Post = v.InferOutput<typeof postSchema>
const transformedPost = v.object({
...postSchema.entries,
published_at: v.date(),
})
type TransformedPost = v.InferOutput<typeof transformedPost>

const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
updatePost: build.mutation<Post, Partial<Post>>({
query(data) {
const { id, ...body } = data
return {
url: `post/${id}`,
method: 'PUT',
body,
}
},
responseSchema: postSchema,
}),
updatePostWithTransform: build.mutation<TransformedPost, Partial<Post>>({
query(data) {
const { id, ...body } = data
return {
url: `post/${id}`,
method: 'PUT',
body,
}
},
rawResponseSchema: postSchema,
transformResponse: (response) => ({
...response,
published_at: new Date(response.published_at),
}),

responseSchema: transformedPost,
}),
}),
})

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