Realtime
WebSocket events, presence & ACK
usePubSub is the client half of the pub/sub feature. It opens a single WebSocket to the events endpoint, subscribes to the topics you name, and streams server events into an h-state store you read reactively — connection status, the event log and presence all live there.
It is resilient by default: a heartbeat keeps the socket warm, drops trigger exponential-backoff reconnection, and every delivered message is acknowledged back to the server so the ACK/redelivery guarantees on the backend actually hold.
Configure it on the backend through the pubsub config block; consume it on the frontend with this one hook. No manual socket lifecycle, no reconnection loops to write.
Hook configuration#
usePubSub(config) takes the identity and topics to subscribe to, plus optional resilience tuning. userId is required — it scopes the connection and is enforced by the maxClientsPerUser guard on the server.
userIdstringRequiredThe authenticated user the socket belongs to. Sent as a query param and used server-side for per-user client limits and targeted delivery.
topicsstring[]OptionalTopics to subscribe to on connect. Changing this array re-subscribes automatically. '*' receives everything you're permitted to see.
Example: ["orders", "notifications:user-42"]
["*"]wsUrlstringOptionalOverride the WebSocket origin. When omitted the hook derives ws://wss:// from window.location, so same-origin deployments need no URL at all.
wsPathstringOptionalThe subscribe path — must match the pubsub.wsPath configured on the backend.
"/api/events/subscribe"autoReconnectbooleanOptionalReconnect automatically after an unexpected close. A clean server close (code 4001) is respected and does not retry.
truemaxReconnectAttemptsnumberOptionalHow many backoff attempts before giving up and surfacing an error on the store.
10reconnectBaseDelaynumberOptionalBase delay in ms for exponential backoff (base · 2^attempt), capped by reconnectMaxDelay.
1000reconnectMaxDelaynumberOptionalUpper bound in ms on any single reconnect delay.
30000heartbeatIntervalnumberOptionalHow often (ms) to send a ping frame so proxies and the server keep the socket alive.
30000debugbooleanOptionalLog connection lifecycle and message handling to the console.
falseWhat the hook returns#
Everything you need to render realtime UI: live connection flags, the typed event list, presence/identity and imperative controls. Reads are reactive — when a new event arrives, components re-render.
1const { isConnected, events, subscribe } = usePubSub({2 userId: user.id,3 topics: ["orders"],4});5 6// ACK is automatic — every event with a messageId is acknowledged7return (8 <section>9 <span data-live={isConnected}>{isConnected ? "live" : "offline"}</span>10 {events.map((e) => (11 <Event key={e.id} topic={e.topic} payload={e.data} />12 ))}13 </section>14);isConnected / isConnectingbooleanOptionalConnection status flags. isConnecting covers both initial connect and reconnect attempts so you can show one 'linking…' state.
eventsPubSubEvent[]OptionalThe received events (id, topic, data, timestamp, receivedAt, messageId, isRedelivery), capped by the store's ring buffer so memory stays bounded.
clientId / subscribedTopicsstring | string[]OptionalThe server-assigned client id and the topics the server confirms you're subscribed to.
error / reconnectAttemptError | numberOptionalThe last connection error (or null) and the current backoff attempt count for diagnostics UI.
subscribe / unsubscribe(topics: string[]) => voidOptionalAdjust subscriptions on a live socket without reconnecting.
connect / disconnect / clearEvents / getEventsByTopicfunctionsOptionalImperative controls: force a (re)connect, tear down cleanly, empty the buffer, or read just one topic's events.
Related sections