Real-time features — live chat, presence, price tickers, collaborative cursors — run over a WebSocket. Wrapping the raw WebSocket API in React means managing a connection lifecycle: it opens, delivers messages, can close unexpectedly (dropped Wi-Fi, server restart), and should auto-reconnect with a capped number of retries. useWebsocket exposes that as { status, lastMessage, send } and handles reconnection and cleanup for you.
Implement useWebsocket(url, { reconnectAttempts = 3, reconnectInterval = 1000 }). Open the socket on mount, track status, surface the latest message, and provide a send that only transmits when open. On an unexpected close, reconnect after the interval up to the attempt cap; a successful open resets the counter. Tear everything down on unmount.
function useWebsocket(url, { reconnectAttempts = 3, reconnectInterval = 1000 }) {
// returns { status, lastMessage, send }
// status: 'connecting' | 'open' | 'closed'
}
const { status, lastMessage, send } = useWebsocket('wss://chat.example/room/1');
useEffect(() => { if (lastMessage) appendMessage(JSON.parse(lastMessage)); }, [lastMessage]);
<button disabled={status !== 'open'} onClick={() => send(JSON.stringify(draft))}>Send</button>
// Retry up to 5 times, 2s apart, on a dropped connection.
const ws = useWebsocket(url, { reconnectAttempts: 5, reconnectInterval: 2000 });
connecting on open-attempt, open in onopen, closed in onclose; surface onmessage data as lastMessage.ws.send when readyState === WebSocket.OPEN; return a boolean so callers know if it went out.setTimeout(connect, reconnectInterval); a successful onopen resets the attempt counter.url or WebSocket.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.