TanStack Query: WebSocket & Real-Time Data

WebSocket-Verbindungen mit TanStack Query für Echtzeit-Updates integrieren – von Subscriptions über Cache-Abgleich bis zur Reconnection-Logik.

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

TL;DR: WebSockets und TanStack Query funktionieren über ein einfaches Muster zusammen: WebSocket-Events beim Mount abonnieren, Updates in den Query-Cache推入 und Query die Reconciliation überlassen. Dieser Leitfaden behandelt WebSocket-Subscriptions, die gecachte Queries aktualisieren, Deduplizierung von Echtzeit- und Polling-Daten, Reconnection-Strategien sowie einen eigenen useWebSocketQuery-Hook.


Einleitung

Echtzeit-Daten sind für moderne SaaS-Anwendungen ein absolutes Muss – kollaboratives Editing, Live-Dashboards, Benachrichtigungs-Badges und Chat. TanStack Query kümmert sich elegant um das Caching des Server-State, doch WebSockets bringen Events mit sich, die den normalen Request-Lebenszyklus umgehen müssen.

Der entscheidende Punkt: WebSocket-Nachrichten sollten den Query-Cache direkt aktualisieren, nicht Refetches auslösen. So erhalten Sie sofortige Updates, die nur die tatsächlich geänderten Daten berühren.


WebSocket-Subscription-Hook

tsx
function useWebSocketSubscription<TData>(
  channel: string,
  onMessage: (data: TData) => void
) {
  useEffect(() => {
    const ws = new WebSocket(`wss://api.tanstackship.com/ws?channel=${channel}`)

    ws.onmessage = (event) => {
      const data = JSON.parse(event.data) as TData
      onMessage(data)
    }

    ws.onclose = () => {
      // Nach 3 Sekunden neu verbinden
      setTimeout(() => {
        new WebSocket(`wss://api.tanstackship.com/ws?channel=${channel}`)
      }, 3000)
    }

    return () => ws.close()
  }, [channel, onMessage])
}

Der Subscription-Hook übernimmt den gesamten WebSocket-Lebenszyklus – Verbindung, Nachrichtenverarbeitung und automatische Reconnection nach dem Schließen. Für Strategien zur Persistenz von Daten während Offline-Phasen und Sync beim Wiederverbinden, see TanStack Query offline support.


Integration mit dem Query-Cache

TanStack Querys Cache ist die zentrale Anlaufstelle für den Server-State. Wenn WebSocket-Events eintreffen, aktualisieren sie den Cache direkt über queryClient.setQueryData und vermeiden so unnötige Netzwerkanfragen. Für fortgeschrittene Muster wie optimistische Updates und Cache-Garbage-Collection, see TanStack Query cache invalidation strategies.

tsx
function useRealtimeDashboard() {
  const queryClient = useQueryClient()
  const { data } = useQuery({
    queryKey: ['dashboard', 'metrics'],
    queryFn: fetchDashboardMetrics,
    refetchInterval: 60_000, // Fallback-Polling
  })

  useWebSocketSubscription('dashboard:metrics', (metric) => {
    queryClient.setQueryData(['dashboard', 'metrics'], (old: any) => {
      if (!old) return old
      return {
        ...old,
        activeUsers: metric.activeUsers,
        recentSignups: old.recentSignups + (metric.newSignup ? 1 : 0),
      }
    })
  })

  return data
}

Dieses Muster hält die Dashboard-Daten über WebSocket-Events frisch, während ein 60-Sekunden-Polling als Fallback erhalten bleibt. Für Caching-Strategien, die diesen Echtzeit-Ansatz ergänzen, see the Edge Caching Strategies Guide.


Vergleich von Echtzeit-Strategien

StrategieLatenzServer-KostenKomplexitätAm besten für
WebSocket + Cache-UpdateSofortHochMittelLive-Dashboards, Chat
Server-Sent Events<1sMittelNiedrigEinweg-Feeds
Short Polling (3s)3-10sNiedrigMinimalNicht-kritische Updates
Long Polling1-5sMittelMittelNur als Fallback
TanStack Query refetchIntervalKonfigurierbarNiedrigMinimalHintergrund-Sync

Fazit

WebSockets + TanStack Query schaffen eine leistungsstarke Echtzeit-Architektur, in der der Cache die Single Source of Truth ist. WebSocket-Events aktualisieren den Cache direkt, während TanStack Query das Fallback-Polling, die Retry-Logik und die Cache-Konsistenz automatisch übernimmt. Für Produktions-Deployments kombinieren Sie dies mit SaaS monitoring and observability, um die WebSocket-Gesundheit und Cache-Performance zu verfolgen.