Optimistic updates with React Query mutations

Maya Patel Jan 2026
2 tabs
import { useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/services/api'
import { Post, PostId } from '@/types'

export function useLikePost() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: async (postId: PostId) => {
      const { data } = await api.post(`/posts/${postId}/like`)
      return data
    },

    onMutate: async (postId: PostId) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({ queryKey: ['posts'] })

      // Snapshot previous value
      const previousPosts = queryClient.getQueryData<Post[]>(['posts'])

      // Optimistically update cache
      queryClient.setQueryData<Post[]>(['posts'], (old) =>
        old?.map((post) =>
          post.id === postId
            ? { ...post, likes_count: post.likes_count + 1, liked_by_user: true }
            : post
        )
      )

      // Return snapshot for rollback
      return { previousPosts }
    },

    onError: (err, postId, context) => {
      // Rollback on error
      if (context?.previousPosts) {
        queryClient.setQueryData(['posts'], context.previousPosts)
      }
    },

    onSettled: () => {
      // Always refetch after error or success
      queryClient.invalidateQueries({ queryKey: ['posts'] })
    },
  })
}
2 files · typescript Explain with highlit

Optimistic updates make UIs feel instant by immediately showing the expected result before the server confirms. When a user likes a post, I update the local cache immediately, submit the request in background, and rollback if it fails. React Query's mutation callbacks (onMutate, onError, onSettled) orchestrate this flow. The onMutate function snapshots the current cache, updates it optimistically, and returns the snapshot for potential rollback. If the mutation fails, onError restores the snapshot. The onSettled callback runs regardless of success/failure to ensure cache consistency. This pattern dramatically improves perceived performance for actions like likes, follows, or simple edits where failures are rare.