Blog>
Snippets

Updating Data with useMutation

Provide an example of using the useMutation hook to submit a new product to the server, including optimistic UI updates.
import { useMutation, useQueryClient } from 'react-query';
import axios from 'axios';

const useSubmitProduct = () => {
  const queryClient = useQueryClient();

  return useMutation(
    (newProduct) => axios.post('/api/products', newProduct),
    {
      // Before the mutation is fired
      onMutate: async (newProduct) => {
        await queryClient.cancelQueries('products');

        const previousProducts = queryClient.getQueryData('products');

        queryClient.setQueryData('products', (old) => [...old, newProduct]);

        return { previousProducts };
      },
      // If the mutation fails, roll back
      onError: (err, newProduct, context) => {
        queryClient.setQueryData('products', context.previousProducts);
      },
      // Always refetch after error or success:
      onSettled: () => {
        queryClient.invalidateQueries('products');
      },
    }
  );
};
This code defines a hook, useSubmitProduct, which uses the useMutation React Query hook to submit a new product to a server endpoint. It showcases optimistic UI updates: before the mutation, it temporarily updates the UI with the expected new product; if the mutation fails, it rolls back to the previous state.