Types
All types are exported from both react-websocket and react-websocket/core.
import type { Status, Snapshot, WebSocketClient } from 'react-websocket';
Status
type Status = 'idle' | 'connecting' | 'open' | 'reconnecting' | 'closed';
Snapshot
The client state that hooks render from. A new object is created on every change, and the same object is returned while nothing changes.
interface Snapshot<In> {
readonly status: Status;
/** Most recent message (after parse/json and schema), kept across reconnects. */
readonly lastMessage: In | undefined;
/**
* Consecutive failed attempts since the last stable connection. A connection that closes
* within `reconnect.minUptime` of opening counts as failed. 0 while open.
*/
readonly attempt: number;
}
CloseInfo
interface CloseInfo {
readonly code: number;
readonly reason: string;
readonly wasClean: boolean;
}
Passed to onClose, the 'close' event and shouldReconnect. Common codes: 1000 normal closure, 1001 going away, 1006 abnormal closure (no close frame, such as a network loss), 1008 policy violation, 1011 server error, 1012 service restart, 1013 try again later, 4000 heartbeat timeout (from this library), 4000–4999 application-defined. By default, 1002, 1003 and 1008 aren't retried (see retryableClose), and a 1013 is retried after a longer wait (see Overloaded servers). A 1012 or 1013 whose reason is a number of seconds is retried after that delay.
MessageError
class MessageError extends Error {
name: string; // 'MessageError'
/** The raw event.data that failed. */
readonly data: unknown;
/** Schema issues, when the message failed `schema`. */
readonly issues: ReadonlyArray<{ readonly message: string }> | undefined;
/** The error thrown by parse/JSON.parse or the schema, if any. */
readonly cause?: unknown;
}
Reported through onError and the 'error' event when an incoming message fails parse/json or schema. The message is not delivered.
import { MessageError } from 'react-websocket';
useWebSocket(url, {
json: true,
schema: Message,
onError(error) {
if (error instanceof MessageError) {
reportToSentry(error, { extra: { data: error.data, issues: error.issues } });
}
}
});
EventMap
The events a client emits and their listener signatures. Use them with client.on(type, listener) and useWebSocketEvent.
interface EventMap<In> {
open: (event: Event) => void;
message: (message: In, event: MessageEvent) => void;
close: (close: CloseInfo) => void;
error: (error: Event | MessageError | Error) => void;
}
An exception thrown by a listener is re-thrown asynchronously, so it reaches your global error reporting without stopping other listeners.
UrlSource
type UrlSource = string | (() => string | Promise<string>);
A function is called before every connection attempt, including reconnects. If it throws or rejects, that counts as a failed attempt and is retried with backoff. See Authentication.
SendData
type SendData = string | ArrayBufferLike | Blob | ArrayBufferView;
Whatever WebSocket.prototype.send accepts in your TypeScript DOM lib.
SendOptions
Per-message options for send().
interface SendOptions {
/** Drop the message instead of queueing it when the socket isn't open. */
volatile?: boolean;
/** Keep only the newest queued message with this key. */
key?: string;
/** Queue ahead of every message queued without `priority`. */
priority?: boolean;
/** While open, drop the message if more than this many bytes are already buffered. */
maxBuffered?: number;
/** Drop the message instead of sending it once it has been queued this many ms. */
maxAge?: number;
/** Called if the message is dropped from the queue without being sent. */
onDrop?: () => void;
}
volatile, key, priority and maxAge only matter while the socket isn't open, and maxBuffered only while it is. Once a message is handed to the browser, nothing can overtake it, so priority can't jump ahead of data already sent. Keep that buffer short by sending bulky streams with maxBuffered.
game.send({ type: 'input', dx, dy }, { volatile: true, maxBuffered: 4096 });
game.send({ type: 'aim', angle }, { key: 'aim' });
game.send({ type: 'leave' }, { priority: true });
See Real-time games.
MigrateOptions
interface MigrateOptions {
url?: UrlSource;
within?: number; // default 0
}
Options for client.migrate().
StandardSchemaV1
The Standard Schema interface. zod (3.24+), valibot (1.0+), arktype (2.0+) and other libraries implement it, so you can pass their schemas directly to the schema option. You don't need to import this type.
WebSocketClient
interface WebSocketClient<In = unknown, Out = unknown> {
readonly url: UrlSource;
readonly ready: Promise<void>;
readonly socket: WebSocket | null;
subscribe(listener: () => void): () => void;
getSnapshot(): Snapshot<In>;
on<K extends keyof EventMap<In>>(type: K, listener: EventMap<In>[K]): () => void;
send(message: Out, options?: SendOptions): boolean;
connect(): void;
close(code?: number, reason?: string): void;
reconnect(): void;
migrate(options?: MigrateOptions): void;
acquire(): () => void;
}