WebSocket channel with reconnect
Problem. Keep a WebSocket connection alive across network blips with exponential backoff.
Solution. useWebSocket handles reconnect and heartbeats; combine it with useWebSocketChannel for typed framing.
ts
import { effect, useWebSocketChannel } from '@bquery/bquery/reactive';
type OrdersFrame = {
channel: string;
data: { type: string; topic?: string; payload?: unknown };
};
const channel = useWebSocketChannel<{ type: 'subscribe'; topic: string }, OrdersFrame>(
'/realtime',
{
protocols: ['app.v1'],
autoReconnect: { delay: 500, maxDelay: 10_000, maxAttempts: Infinity, factor: 2 },
heartbeat: { interval: 25_000, message: 'ping' },
}
);
const orders = channel.subscribe('orders');
effect(() => {
const frame = orders.data.value;
if (frame) render(frame.data);
});
// Send typed frames
channel.publish('orders', { type: 'subscribe', topic: 'orders' });Why it works. Exponential backoff prevents reconnect storms; heartbeats keep proxies from idling out the connection. channel.ws.dispose() tears everything down deterministically.