javascript - Redux RTK Query: Invalidando solo un elemento de la lista
Tengo la siguiente API definida para la consulta RTK:
export const postsApi = createApi({
reducerPath: "postsApi",
baseQuery: fetchBaseQuery({ baseUrl: 'https://myservice.co/api/v2/' }),
tagTypes: ["Posts"],
endpoints: (builder) => ({
getAllPosts: builder.query({
query: () => ({ method: "GET", url: "/posts" }),
transformResponse: (response) => response.posts,
providesTags: (result) =>
result
? [
...result.map(({ id }) => ({ type: "Posts", id })),
{ type: "Posts", id: "LIST" },
]
: [{ type: "Posts", id: "LIST" }],
}),
updatePost: builder.mutation({
query: ({ postId, ...body }) => ({
url: `/posts/${postId}`,
method: "POST",
config: { body },
}),
invalidatesTags: (_, __, arg) => [{ type: "Posts", id: arg.id }],
}),
getPost: builder.query({
query: (postId) => ({
method: "GET",
url: `/posts/${postId}`,
}),
providesTags: (_, __, id) => [{ type: "Posts", id }],
}),
}),
});
export const { useGetAllPostsQuery, useUpdatePostMutation, useGetPostQuery } = postsApi;
Lo que me gustaría que esto hiciera es que cuando se llame a updatePost con éxito, solo invalide la caché de una sola publicación y use la consulta getPost para volver a obtener la información en lugar de getAllPosts. ¿Es esto de alguna manera posible? Las publicaciones se muestran en una tabla obtenida con la consulta getAllPosts.
Respuesta #1
No. RTK-Query es una caché de documentos (respuesta completa=documento), no una caché normalizada. No sabe nada sobre el contenido de las respuestas en caché ni su estructura, y nunca intentará 'unir' nada allí por sí mismo.
Puedes hacer eso manualmente con una actualización optimista, pero todo lo que RTK-Q hace automáticamente es volver a obtener datos, lo cual debería ser más que suficiente en la mayoría de los casos de uso.
Respuesta #2
Puedes manejar este caso actualizando manualmente la caché de manera pesimista u optimista en el endpoint updatePost.
Usaremos el método updateQueryData en la API de rtk para actualizar una entrada de caché ya existente
Porque pesimista debes devolver la nueva versión de la publicación como resultado de tu mutación. Luego actualizas la caché de la lista buscando la publicación que se actualizará en la lista :
updatePost: builder.mutation({
query: ({ postId, ...body }) => ({
url: `/posts/${postId}`,
method: "POST",
config: { body },
}),
invalidatesTags: (_, __, arg) => [{ type: "Posts", id: arg.id }],
async onQueryStarted({...patch},{dispatch, queryFulfilled}) {
//here you can do optimistic update using the patch values
//or you can wait for the mutation result
const {data: updatedPost} = await queryFulfilled;
const patchResult = dispatch(
postApi.util.updateQueryData('getAllPosts',undefined,(draft)=>{
const cachedPost = draft.find(p => p.id === updatedPost.id);
if (t) {
Object.assign(cachedPost, updatedPost);
}
})
);
}
}),