HighX
Client

Without React

HighXClient directly — for another framework, or no framework.

HighXClient owns one connection and all of its semantics. Reach for it when you are building a binding for another framework, using HighX without one, or writing tests.

import { HighXClient, webSocketFactory } from "@highx/client";

const client = new HighXClient({ socket: webSocketFactory(url, WebSocket) });

const release = client.subscribe("notes.list", { color: "amber" }, (entry) => {
  render(entry.value);
});

release();   // unsubscribe

Everything else — reconnect, resume, deduplication, and the mutation queue — happens without your involvement. → Connection

Mutating

try {
  const id = await client.mutate("notes.create", { title: "New" }, {});
} catch (error) {
  if (isConflictError(error)) offerAChoice();
}

mutate resolves with whatever the handler returned and rejects with a RemoteError carrying the server's code. Match on the code, never the message.

Options

new HighXClient({
  socket: webSocketFactory(url, WebSocket),
  scheduler,                 // inject timers
  onStatusChange: (status) => setBanner(status),
  maxQueuedMutations: 100,
});

The socket is injected as a SocketFactory and timers as a Scheduler. That is what lets every reconnect path be tested deterministically — no browser, no real waiting — and it also means you can supply your own transport or clock.

The cache

client.cache is the single place query state lives. A binding reads it and subscribes to its notifications; it must never apply frames into a cache of its own, because once the client owns a cache, re-applying into the same one is an infinite notification loop.

Notifications are paced; values are not. The cache records a new value synchronously — a reader always sees the latest — while the notification is collapsed within a frame. Twenty people typing costs twenty patches and one render.

Building a React-style binding

A transport is all @highx/react needs: cache, subscribe, mutate, and close. See writing a transport by hand for the whole implementation — it is about twenty lines.

On this page