React cookbook · Advanced

Show live updates over WebSockets

Update a dashboard in real time when the server pushes events, with reconnects.

Approach

Keep server data in TanStack Query and use a WebSocket only for change notifications: on each message, update or invalidate the relevant query. Wrap the socket in a hook that reconnects with exponential backoff and cleans up on unmount.

Solution

import { useEffect } from "react";
import { useQueryClient } from "@tanstack/react-query";

type ServerEvent = { type: "order.updated"; order: Order } | { type: "orders.changed" };

export function useLiveOrders() {
  const qc = useQueryClient();

  useEffect(() => {
    let socket: WebSocket | null = null;
    let attempt = 0;
    let timer: ReturnType<typeof setTimeout>;
    let closed = false;

    const connect = () => {
      socket = new WebSocket(`${location.protocol === "https:" ? "wss" : "ws"}://${location.host}/ws/orders`);
      socket.onopen = () => { attempt = 0; };
      socket.onmessage = (msg) => {
        const event = JSON.parse(msg.data) as ServerEvent;
        if (event.type === "order.updated") {
          qc.setQueryData<Order[]>(["orders"], (old = []) => old.map((o) => (o.id === event.order.id ? event.order : o)));
        } else {
          qc.invalidateQueries({ queryKey: ["orders"] });
        }
      };
      socket.onclose = () => {
        if (closed) return;
        const delay = Math.min(30_000, 1000 * 2 ** attempt++) + Math.random() * 500;
        timer = setTimeout(connect, delay);
        qc.invalidateQueries({ queryKey: ["orders"] });     // resync after gaps
      };
    };
    connect();

    return () => { closed = true; clearTimeout(timer); socket?.close(); };
  }, [qc]);
}

Pitfalls

  • Reconnect storms without backoff/jitter.
  • Missing events while disconnected — refetch on reconnect.
  • Opening a socket per component instead of one shared connection.

Variations

  • Server-Sent Events (EventSource) when updates are one-way.
  • Managed realtime services (Ably, Pusher, Supabase Realtime).

Further reading: MDN: WebSocket

Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket

More React recipes