Blog>
Snippets

Optimistic Updates in an Offline-First App

Demonstrate how to implement optimistic UI updates with React Query to instantly reflect changes in the UI caused by mutations (create/update/delete operations), even when offline.
import { useMutation, useQueryClient } from 'react-query';

function useAddItem() {
  const queryClient = useQueryClient();
  return useMutation(addItemToServer, {
    // On mutate, we optimistically update the UI
    onMutate: async newItem => {
      await queryClient.cancelQueries('items');

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

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

      return { previousItems };
    },
    // On failure, we roll back to the previous state
    onError: (err, newItem, context) => {
      queryClient.setQueryData('items', context.previousItems);
    },
    // After mutation, refetch the items query to sync with the server
    onSettled: () => {
      queryClient.invalidateQueries('items');
    },
  });
}
This code snippet demonstrates how to optimistically update the UI with React Query when adding a new item to a list. It uses `useMutation` to perform the add operation, with optimistic updates on mutate, rollback on error, and refetching after mutation to ensure data consistency.
const { mutate } = useAddItem();

function addItem() {
  const newItem = { id: Date.now(), text: 'New Item' };
  mutate(newItem);
}
This function uses the custom `useAddItem` hook to add a new item. It defines the new item and calls `mutate` with it, triggering the optimistic update logic defined in `useAddItem`.