Blog>
Snippets

Optimistic Updates in React Applications

Illustrate how to implement optimistic updates using the useMutation hook in React Query, showing a scenario where a post is updated and the UI optimistically reflects the change before server confirmation.
import { useMutation, useQueryClient } from 'react-query';

const updatePost = async (postData) => {
  // Assume this function sends the updated post data to your server
  // and returns the updated post data
  const response = await fetch('https://yourapi.com/posts/' + postData.id, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(postData),
  });

  if (!response.ok) {
    throw new Error('Network response was not ok');
  }

  return response.json();
};
Defines an asynchronous function updatePost that sends updated post data to the server and returns the updated post data. This function will be used in our mutation.
function PostEditor({ post }) {
  const queryClient = useQueryClient();
  const { mutate: updatePostData } = useMutation(updatePost, {
    onMutate: async (newPost) => {
      // Cancel any outgoing refetches for the posts query
      await queryClient.cancelQueries('posts');

      // Snapshot the previous value
      const previousPosts = queryClient.getQueryData('posts');

      // Optimistically update to the new value
      queryClient.setQueryData('posts', (old) => {
        return old.map((post) => post.id === newPost.id ? { ...post, ...newPost } : post);
      });

      return { previousPosts };
    },
    onError: (err, newPost, context) => {
      // Roll back to the previous value
      queryClient.setQueryData('posts', context.previousPosts);
    },
    onSettled: () => {
      // Refetch after error or success:
      queryClient.invalidateQueries('posts');
    },
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    const updatedPost = { id: post.id, title: formData.get('title'), content: formData.get('content') };

    updatePostData(updatedPost);
  };

  return (
    /* JSX for form fields */
    // Assume a form with title and content input fields
    // and a submit button calling handleSubmit on submit
  );
}
Creates a PostEditor component that uses useMutation with optimistic updates. On submitting the form with updated post data, it optimisticly updates the UI before waiting for server confirmation. If the update fails, the UI is rolled back to its previous state.