TanStack Query: Optimistic Updates Patterns — Instant UI mit Rollback

Optimistic Updates in TanStack Query: sofortiges UI-Feedback mit Rollback-Schutz. Mutation-Patterns, Cache-Manipulation und Error Recovery, mit TypeScript-Beispielen.

Sam Rivera
Sam Rivera
1. Juni 20266 min read
Auch verfügbar auf:English · 中文

TL;DR: Optimistic Updates lassen Ihre SaaS-App sofort wirken, indem das UI aktualisiert wird, bevor der Server antwortet. TanStack Querys onMutate-Callback liefert ein sauberes Pattern: Cache snapshotten, die optimistische Änderung anwenden und bei Fehlern zurückrollen. Dieser Guide deckt drei Patterns ab — Einzel-Updates, Listen-Mutationen und paginierte Listen — mit vollständigen TypeScript-Beispielen.


Einleitung

Nutzer nehmen Geschwindigkeit als Feature wahr. Ein 300-ms-Servercall wirkt träge. Optimistic Updates eliminieren diese Wahrnehmung, indem sie das Ergebnis sofort anzeigen und im Hintergrund mit dem Server abgleichen.

TanStack Query bietet First-Class-Support für dieses Pattern über die Lifecycle-Callbacks des useMutation-Hooks.


Basis-Optimistic-Update

tsx
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { updateProductFn } from '../server/products'

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

  return useMutation({
    mutationFn: updateProductFn,
    onMutate: async (newProduct) => {
      await queryClient.cancelQueries({ queryKey: ['product', newProduct.id] })
      const previous = queryClient.getQueryData(['product', newProduct.id])
      queryClient.setQueryData(['product', newProduct.id], newProduct)
      return { previous }
    },
    onError: (err, newProduct, context) => {
      queryClient.setQueryData(['product', newProduct.id], context?.previous)
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['products'] })
    },
  })
}

Listen-Mutation mit Optimistic Update

Bei List-Queries müssen Sie das gecachte Array manipulieren:

tsx
useMutation({
  mutationFn: createProductFn,
  onMutate: async (newProduct) => {
    await queryClient.cancelQueries({ queryKey: ['products'] })
    const previous = queryClient.getQueryData(['products'])

    queryClient.setQueryData(['products'], (old: any) => ({
      pages: old.pages.map((page: any, i: number) =>
        i === 0 ? { ...page, items: [newProduct, ...page.items] } : page
      ),
      pageParams: old.pageParams,
    }))

    return { previous }
  },
  onError: (err, _, context) => {
    queryClient.setQueryData(['products'], context?.previous)
  },
})

Rollback-Entscheidungsmatrix

FehlertypUX-ReaktionTechnische Aktion
NetzwerkfehlerRevert + ToastonError-Rollback
ValidierungsfehlerField-Error anzeigenOptimistisch halten + als ungültig markieren
AutorisierungsfehlerRevert + RedirectonError + Router-Redirect
Konflikt (stale Daten)Revert + RefetchonSettled-Invalidierung

Fazit

Optimistic Updates verbessern die wahrgenommene Performance drastisch. TanStack Querys Mutation-Callbacks liefern ein sauberes, testbares Pattern — ohne die Komplexität manuellen State-Managements.

Kombinieren Sie Optimistic Updates mit den richtigen Cache-Invalidierungs-Strategien für eine vollständige Datensynchronisation. Wie Server Functions sich in TanStack Query integrieren, lernen Sie in Server Functions Best Practices.