Package Exports
- react-websocket-kit
Readme
react-websocket-kit
A high-performance React WebSocket client with channel/event pub-sub routing, heartbeat keep-alive, auto-reconnect with exponential backoff, and UMD/CDN support.
Features
- 🔌
useWebSockethook — Component-level WebSocket with full lifecycle control - 📡 Channel & Event Pub/Sub — Subscribe to structured
{ channel, event, payload }messages - 🔁 Auto-Reconnect — Exponential backoff with configurable attempts and max delay
- 💓 Heartbeat Keep-Alive — Detect dead connections and self-heal automatically
- 🌐 Shared Connections —
<WebSocketProvider>shares a single socket across your component tree - 📦 Dual Build — ESM (
import) and UMD (<script>tag) outputs - 🏷️ Full TypeScript — Ships
.d.tsdeclarations for every export
Installation
npm / yarn / pnpm
npm install react-websocket-kit
# or
yarn add react-websocket-kit
# or
pnpm add react-websocket-kitCDN (Script Tag)
<!-- React 18 (peer dependency) -->
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<!-- React WebSocket Kit -->
<script src="https://unpkg.com/react-websocket-kit/dist/index.umd.cjs"></script>
<script>
// All exports available on the global namespace:
const { useWebSocket, WebSocketProvider, useWebSocketEvent, ReadyState } = ReactWebSocketKit;
</script>Quick Start
1. Basic Hook Usage
Use useWebSocket for a single component-scoped connection:
import { useWebSocket, ReadyState } from 'react-websocket-kit';
function LiveStatus() {
const { readyState, sendRaw, lastMessage } = useWebSocket('ws://localhost:8080');
return (
<div>
<p>Status: {readyState === ReadyState.OPEN ? '🟢 Connected' : '🔴 Offline'}</p>
<button onClick={() => sendRaw('Hello Server!')}>Send</button>
<p>Last message: {lastMessage?.data}</p>
</div>
);
}2. Channel & Event Pub/Sub
All structured messages follow a standard envelope:
{
"channel": "chat:lobby",
"event": "new_message",
"payload": { "sender": "Alice", "text": "Hello!" }
}Emitting events
const { emit } = useWebSocket('ws://localhost:8080');
// Sends: {"channel":"chat:lobby","event":"new_message","payload":{"text":"Hi"}}
emit('chat:lobby', 'new_message', { text: 'Hi' });Subscribing to events (imperative)
const { subscribe } = useWebSocket('ws://localhost:8080');
useEffect(() => {
const unsubscribe = subscribe('chat:lobby', 'new_message', (payload) => {
console.log(payload.text);
});
return unsubscribe;
}, []);Subscribing to events (declarative hook)
import { useWebSocketEvent } from 'react-websocket-kit';
function ChatMessages() {
const [messages, setMessages] = useState([]);
// Auto-subscribes on mount, auto-unsubscribes on unmount
useWebSocketEvent('chat:lobby', 'new_message', (payload) => {
setMessages((prev) => [...prev, payload]);
});
return (
<ul>
{messages.map((m, i) => (
<li key={i}>{m.sender}: {m.text}</li>
))}
</ul>
);
}3. Shared Connection via Provider
Wrap your app in <WebSocketProvider> to share a single socket across all child components:
import { WebSocketProvider, useSharedWebSocket, useWebSocketEvent } from 'react-websocket-kit';
function App() {
return (
<WebSocketProvider url="ws://localhost:8080" options={{ heartbeat: true }}>
<Dashboard />
<Notifications />
</WebSocketProvider>
);
}
function Dashboard() {
const { emit, readyState } = useSharedWebSocket();
// emit(), sendRaw(), subscribe() all available here
}
function Notifications() {
useWebSocketEvent('alerts', 'new_alert', (payload) => {
alert(payload.message);
});
}API Reference
useWebSocket(url, options?)
The core hook. Returns a connection instance.
| Parameter | Type | Description |
|---|---|---|
url |
string | () => string | Promise<string> |
WebSocket server URL or async resolver |
options |
WebSocketOptions |
Configuration (see below) |
WebSocketOptions
| Option | Type | Default | Description |
|---|---|---|---|
manual |
boolean |
false |
If true, won't connect on mount — call connect() manually |
reconnect |
boolean | ReconnectOptions |
true |
Auto-reconnect config (see below) |
heartbeat |
boolean | HeartbeatOptions |
false |
Keep-alive config (see below) |
queryParams |
Record<string, string | number | boolean> |
— | Appended to the connection URL |
protocols |
string | string[] |
— | WebSocket sub-protocols |
onOpen |
(event: Event) => void |
— | Fires on connection open |
onClose |
(event: CloseEvent) => void |
— | Fires on connection close |
onMessage |
(event: MessageEvent) => void |
— | Fires on every raw incoming message |
onError |
(event: Event) => void |
— | Fires on WebSocket error |
ReconnectOptions
| Option | Type | Default | Description |
|---|---|---|---|
attempts |
number |
Infinity |
Max reconnect attempts |
delay |
number |
2000 |
Initial delay (ms) |
maxDelay |
number |
30000 |
Maximum delay cap (ms) |
exponential |
boolean |
true |
Use exponential backoff |
HeartbeatOptions
| Option | Type | Default | Description |
|---|---|---|---|
message |
string | object |
'ping' |
Payload sent as keep-alive |
interval |
number |
30000 |
How often to ping (ms) |
timeout |
number |
10000 |
Time to wait for pong before closing (ms) |
pongMessage |
string | object |
— | Expected server response to reset timeout |
Return Value (UseWebSocketReturn)
| Property | Type | Description |
|---|---|---|
readyState |
ReadyState |
Current connection state |
lastMessage |
MessageEvent | null |
Last raw message event received |
sendRaw(data) |
function |
Send a raw string or binary payload |
emit(channel, event, payload) |
function |
Send a structured { channel, event, payload } JSON message |
subscribe(channel, event, cb) |
function |
Register a listener. Returns an unsubscribe function |
unsubscribe(channel, event, cb) |
function |
Remove a specific listener |
connect() |
function |
Manually open/reconnect the connection |
disconnect() |
function |
Close the connection (prevents auto-reconnect) |
getWebSocket() |
function |
Access the underlying WebSocket instance |
useWebSocketEvent(channel, event, callback, connection?)
Declarative hook that subscribes to a specific channel and event. Automatically cleans up on unmount.
useWebSocketEvent('orders', 'status_update', (payload) => {
console.log(`Order ${payload.orderId} is now ${payload.status}`);
});| Parameter | Type | Description |
|---|---|---|
channel |
string |
Channel name to listen on |
event |
string |
Event name to listen for |
callback |
(payload: T) => void |
Handler called with the event payload |
connection |
UseWebSocketReturn |
(Optional) Custom connection. If omitted, uses nearest <WebSocketProvider> |
<WebSocketProvider>
React context provider that creates and shares a single WebSocket connection.
<WebSocketProvider url="ws://localhost:8080" options={{ heartbeat: true }}>
{children}
</WebSocketProvider>| Prop | Type | Description |
|---|---|---|
url |
string | () => string | Promise<string> |
WebSocket server URL |
options |
WebSocketOptions |
Same options as useWebSocket |
useSharedWebSocket()
Access the shared connection created by the nearest <WebSocketProvider>. Returns the same UseWebSocketReturn shape as useWebSocket.
const { emit, readyState, subscribe, disconnect } = useSharedWebSocket();ReadyState Enum
| Value | Constant | Meaning |
|---|---|---|
0 |
ReadyState.CONNECTING |
Socket is connecting |
1 |
ReadyState.OPEN |
Connection is open and ready |
2 |
ReadyState.CLOSING |
Connection is closing |
3 |
ReadyState.CLOSED |
Connection is closed |
-1 |
ReadyState.UNINSTANTIATED |
Hook mounted with manual: true, not yet connected |
Message Protocol
When using emit() and subscribe(), all messages are serialized as JSON with this structure:
interface WebSocketEventMessage<T = any> {
channel: string; // e.g. "chat:lobby", "market", "notifications"
event: string; // e.g. "new_message", "price_update", "alert"
payload: T; // any JSON-serializable data
}Server-side, parse incoming messages as JSON and route by channel + event. Messages that don't match this structure are still delivered to the onMessage callback and lastMessage — so raw text and binary payloads work seamlessly alongside structured events.
Example: Node.js Echo Server
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', (data) => {
const msg = data.toString();
// Heartbeat
if (msg === 'ping') {
ws.send('pong');
return;
}
// Parse structured message
try {
const parsed = JSON.parse(msg);
const { channel, event, payload } = parsed;
// Broadcast to all clients
for (const client of wss.clients) {
if (client.readyState === 1) {
client.send(JSON.stringify({ channel, event, payload }));
}
}
} catch {
// Echo raw messages
ws.send(`Echo: ${msg}`);
}
});
});CDN Usage Example
A complete standalone HTML page using react-websocket-kit from a CDN:
<!DOCTYPE html>
<html>
<head>
<title>CDN WebSocket Demo</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://unpkg.com/react-websocket-kit/dist/index.umd.cjs"></script>
<script type="text/babel">
const { WebSocketProvider, useSharedWebSocket, useWebSocketEvent, ReadyState } = ReactWebSocketKit;
function Chat() {
const { emit, readyState } = useSharedWebSocket();
const [messages, setMessages] = React.useState([]);
useWebSocketEvent('chat', 'message', (payload) => {
setMessages(prev => [...prev, payload]);
});
const send = () => {
emit('chat', 'message', { text: 'Hello!', sender: 'CDN User' });
};
return (
<div>
<p>Status: {readyState === ReadyState.OPEN ? 'Connected' : 'Offline'}</p>
<button onClick={send} disabled={readyState !== ReadyState.OPEN}>Send</button>
<ul>
{messages.map((m, i) => <li key={i}>{m.sender}: {m.text}</li>)}
</ul>
</div>
);
}
function App() {
return (
<WebSocketProvider url="ws://localhost:8080">
<Chat />
</WebSocketProvider>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>TypeScript
All types are exported and available:
import type {
WebSocketOptions,
WebSocketEventMessage,
UseWebSocketReturn,
ReconnectOptions,
HeartbeatOptions,
EventListenerCallback,
WebSocketProviderProps,
} from 'react-websocket-kit';License
MIT