Skip to main content

Live queries

A LiveQuery is the reactive store that powers useLiveList. It does the hybrid fetch + subscribe dance, applies optimistic mutations, tracks connection status, and exposes a stable snapshot for useSyncExternalStore. Use it directly in non-React apps or for custom integrations.

import { createLiveQuery, statusLabel } from "covara/client";

const todos = client.resource<Todo>("/api/todos");

const liveQuery = createLiveQuery(todos, {
filter: 'userId=="123"',
orderBy: "position",
limit: 100,
}, {
onAuthError: () => redirectToLogin(),
getPendingCount: () => client.getPendingCount(),
onIdRemapped: (optimisticId, serverId) => console.log(`${optimisticId} -> ${serverId}`),
});

const state = liveQuery.getSnapshot(); // stable reference
// { items, status, error, pendingCount, lastSeq }

const unsubscribe = liveQuery.subscribe(() => render(liveQuery.getSnapshot()));

liveQuery.mutate.create({ title: "New" });
liveQuery.mutate.update("123", { completed: true });
liveQuery.mutate.delete("123");

await liveQuery.refresh();
statusLabel(state.status, state.pendingCount); // "Live", "Loading…", "Offline (3 pending)"
liveQuery.destroy();

State

interface LiveQueryState<T> {
items: T[];
status: "loading" | "live" | "reconnecting" | "offline" | "error";
error: Error | null;
pendingCount: number;
lastSeq: number;
}

How it stays live

  1. Fetch the initial page via GET.
  2. Subscribe with skipExisting=true, passing the known IDs.
  3. Apply added/changed/removed events to the in-memory list, honoring the subscription mode.
  4. Apply optimistic mutations immediately; reconcile against server responses (and remap temporary IDs).
  5. On invalidate (sequence gap, auth change, backpressure), refetch.

The store is cached per (path, options) by the client, so multiple components reading the same query share one subscription. client.invalidate(...) and client.prefetch(...) operate on these caches — see Overview.

Low-level subscriptions

For full control without the store, subscribe directly — see Subscriptions → low-level API.