Blog>
Snippets

Optimistic Updates for Mutations

Implement an optimistic UI update pattern using React Query's mutations to instantly update the UI before server confirmation.
import { useMutation, useQueryClient } from 'react-query';

const useAddItem = () => {
  const queryClient = useQueryClient();
  return useMutation(addItemToServer, {
    // Optimistically update the cache before the server response arrives
    onMutate: async newItem => {
      await queryClient.cancelQueries('items');

      const previousItems = queryClient.getQueryData('items');

      queryClient.setQueryData('items', old => [...old, newItem]);

      return { previousItems };
    },
    // On success, do nothing as we've already optimistically updated the list
    onSuccess: () => {},
    // If the mutation fails, roll back to the previous items list
    onError: (err, newItem, context) => {
      queryClient.setQueryData('items', context.previousItems);
    },
    // Always refetch after error or success:
    onSettled: () => {
      queryClient.invalidateQueries('items');
    },
  });
};
This code defines a custom hook `useAddItem` using React Query's `useMutation` to handle adding an item to a server. Upon calling the mutation, it optimistically updates the cache ('items') with the new item before the server confirms the addition. If the server operation fails, the cache is rolled back to its previous state. Whether the mutation succeeds or fails, `invalidateQueries` is called to ensure the cache is in sync with the server.