Performing CRUD Operations with useMutation
Illustrate how to use the useMutation hook for creating, updating, and deleting data on the server, including how to manage optimistic updates.
import { useMutation, useQueryClient } from 'react-query';
const useCreateItem = () => {
const queryClient = useQueryClient();
return useMutation(createItem, {
// On mutation success, invalidate cache to refetch
onSuccess: () => {
queryClient.invalidateQueries('items');
},
// Optimistically update the cache to include the new item
onMutate: async (newItem) => {
await queryClient.cancelQueries('items');
const previousItems = queryClient.getQueryData('items');
queryClient.setQueryData('items', (old) => [...old, newItem]);
return { previousItems };
},
// Revert optimistic update if mutation fails
onError: (err, newItem, context) => {
queryClient.setQueryData('items', context.previousItems);
},
});
};
This snippet defines a custom hook `useCreateItem` that uses `useMutation` for creating a new item on the server. It optimistically updates the cache before the mutation is completed and reverts changes if the mutation fails.
const useUpdateItem = () => {
const queryClient = useQueryClient();
return useMutation(updateItem, {
onSuccess: () => {
queryClient.invalidateQueries('items');
},
onMutate: async (updatedItem) => {
await queryClient.cancelQueries('items');
const previousItems = queryClient.getQueryData('items');
queryClient.setQueryData('items', (oldItems) => oldItems.map(item => item.id === updatedItem.id ? {...item, ...updatedItem} : item));
return { previousItems };
},
onError: (err, newItem, context) => {
queryClient.setQueryData('items', context.previousItems);
},
});
};
This code snippet creates a `useUpdateItem` hook that utilizes `useMutation` for updating an item on the server. It manages optimistic updates by immediately applying changes to the cache and reverting on failure.
const useDeleteItem = () => {
const queryClient = useQueryClient();
return useMutation(deleteItem, {
onSuccess: () => {
queryClient.invalidateQueries('items');
},
onMutate: async (itemId) => {
await queryClient.cancelQueries('items');
const previousItems = queryClient.getQueryData('items');
queryClient.setQueryData('items', (oldItems) => oldItems.filter(item => item.id !== itemId));
return { previousItems };
},
onError: (err, itemId, context) => {
queryClient.setQueryData('items', context.previousItems);
},
});
};
This code illustrates the `useDeleteItem` hook which uses `useMutation` to delete an item on the server. It includes an optimistic update where the item is immediately removed from the cache, with a rollback mechanism in case of failure.