Blog>
Snippets

Using Optimistic Updates with React Query Mutations

Provide a code example of how to implement optimistic updates in a React application using mutations with React Query. This involves updating the UI immediately with the expected result of a mutation before the server response is received, then synchronizing the UI with the actual server response.
import { useMutation, useQueryClient } from 'react-query';
Imports the useMutation hook and useQueryClient from React Query for managing mutations and accessing the query client.
const updateTodo = async (todo) => {
  // Replace with your update API call
  return fetch('/api/todo', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(todo),
  }).then(res => res.json());
};
Defines the asynchronous function updateTodo that sends a PUT request to the server to update a todo item. This is a placeholder for your actual update logic.
const useUpdateTodo = () => {
  const queryClient = useQueryClient();
  return useMutation(updateTodo, {
    onMutate: async newTodo => {
      await queryClient.cancelQueries('todos');
      const previousTodos = queryClient.getQueryData('todos');
      queryClient.setQueryData('todos', old => old.map(todo => todo.id === newTodo.id ? { ...todo, ...newTodo } : todo));
      return { previousTodos };
    },
    onError: (err, newTodo, context) => {
      queryClient.setQueryData('todos', context.previousTodos);
    },
    onSettled: () => {
      queryClient.invalidateQueries('todos');
    }
  });
};
Defines the custom hook useUpdateTodo that utilizes React Query's useMutation. It handles the optimistic update by temporarily updating the UI with the expected newTodo state, and rolls back if the API call fails.