#
MutationsUnlike 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.
info
Notice the onStart
, onSuccess
, onError
methods? Be sure to check out how they can be used for optimistic updates
#
Type interfaces#
Basic MutationThis 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 a EditablePostName
component is rendered that allows us to edit the name of the post.
#
Advanced mutations with revalidationIn 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. Before getting started, let's cover some new terms used when defining an endpoint in a service:
#
TagsFor RTK Query, tags are just a name that you can give to a specific collection of data to control caching and invalidation behavior, and are defined in an tagTypes
argument. For example, in an application that has both Posts
and Users
, you would define tagTypes: ['Posts', 'Users']
when calling createApi
.
#
ProvidesA query can provide tags to the cache. The providesTags
argument can either be an array of string
(such as ['Posts']
), {type: string, id?: string|number}
or a callback that returns such an array. That function will be passed the result as the first argument, the response error as the second argument, and the argument originally passed into the query
method as the third argument. Note that either the result or error arguments may be undefined based on whether the query was successful or not.
#
InvalidatesA mutation can invalidate specific tags in the cache. The invalidatesTags
argument can either be an array of string
(such as ['Posts']
), {type: string, id?: string|number}
or a callback that returns such an array. That function will be passed the result as the first argument, the response error as the second argument, and the argument originally passed into the query
method as the third argument. Note that either the result or error arguments may be undefined based on whether the mutation was successful or not.
#
Scenarios and BehaviorsRTK Query provides a lot of flexibility for how you can manage the invalidation behavior of your service. Let's look at a few different scenarios:
#
Invalidating everything of a typeWhat to expect
When addPost
is triggered, it would cause each PostDetail
component to go back into a isFetching
state because addPost
invalidates the root tag, which causes every query that provides 'Posts' to be re-run. In most cases, this may not be what you want to do. Imagine if you had 100 posts on the screen that all subscribed to a getPost
query โ in this case, you'd create 100 requests and send a ton of unnecessary traffic to your server, which we're trying to avoid in the first place! Even though the user would still see the last good cached result and potentially not notice anything other than their browser hiccuping, you still want to avoid this.
#
Selectively invalidating listsKeep an eye on the provides
property of getPosts
- we'll explain why after.
Note about 'LIST' and
id
s
LIST
is an arbitrary string - technically speaking, you could use anything you want here, such asALL
or*
. The important thing when choosing a custom id is to make sure there is no possibility of it colliding with an id that is returned by a query result. If you have unknown ids in your query results and don't want to risk it, you can go with point 3 below.- You can add many tag types for even more control
[{ type: 'Posts', id: 'LIST' }, { type: 'Posts', id: 'SVELTE_POSTS' }, { type: 'Posts', id: 'REACT_POSTS' }]
- If the concept of using an
id
like 'LIST' seems strange to you, you can always add anothertagType
and invalidate it's root, but we recommend using theid
approach as shown.
What to expect
When addPost
is fired, it will only cause the PostsList
to go into an isFetching
state because addPost
only invalidates the 'LIST' id, which causes getPosts
to rerun (because it provides that specific id). So in your network tab, you would only see 1 new request fire for GET /posts
. Once that resolves and assuming it returned updated data for ids 1, 2, and 3, the PostDetail
components would then rerender with the latest data.
#
Commented Posts ServiceThis 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.