esc

Type to search...

The choice

react-use-websocket is the default pick when you reach for a WebSocket hook in React. It wraps the browser WebSocket API into a clean useWebSocket hook, handles reconnection, and exposes sendMessage / lastMessage. For simple realtime views it's more than enough.

react-socket sits one floor up. It's still unopinionated about your protocol or state, but it orchestrates the things you start to hand-roll the moment your app gets real: typed messages, ref counted subscriptions shared across components, in-flight tracking with ack IDs, offline queuing, and a dev inspector. If you're building a chat room, a trading UI, or a streaming LLM client, that's where the boilerplate eats weeks.

Where each one sits

Libraries that do less than react-socket leave you to implement subscription dedup, in-flight tracking, offline replay, and type propagation yourself. Libraries that do more pick a protocol (STOMP, GraphQL subscriptions, Phoenix Channels) and lock you to it.

react-use-websocket sits firmly in the "less" camp: a thin, friendly hook around the browser primitive. react-socket stays protocol-agnostic but handles the transport plumbing around the socket, so your app code stays focused on what the messages mean, not how they arrive.

Feature by feature

Feature comparison between react-socket and react-use-websocket

@luciodale/react-socket Orchestrator, protocol agnostic
Typed message schemas
Yes
Automatic reconnection
Yes
Ref counted subscriptions
Yes
In-flight tracking with ack IDs
Yes
Offline message queue
Yes
Keep alive ping / pong
Yes
DevTools inspector
Yes
Pluggable transport
Yes
API shape
Manager class + hooks
Bundle size
~5 kB gzipped
react-use-websocket Thin hook around browser WebSocket
Typed message schemas
No
Automatic reconnection
Yes
Ref counted subscriptions
No
In-flight tracking with ack IDs
No
Offline message queue
No
Keep alive ping / pong
Partial
DevTools inspector
No
Pluggable transport
No
API shape
Single hook
Bundle size
~3 kB gzipped

Type safety in practice

With react-use-websocket, lastJsonMessage is unknown and sendJsonMessage accepts any JSON-serializable value. You either cast everywhere or build a wrapper that enforces your protocol. Fine for a toy, brittle for an app.

use-websocket.tsx
// react-use-websocket: types stop at the hook boundary
const { sendJsonMessage, lastJsonMessage } = useWebSocket(url);

sendJsonMessage({ type: "ecoh", text: "hi" });    // typo compiles
const msg = lastJsonMessage as ServerMsg;          // trust me bro

With react-socket, WebSocketManager<TClientMsg, TServerMsg> propagates your protocol through every callback. Rename a field and the compiler lists the callsites that need to change.

react-socket.tsx
// react-socket: types flow end to end
const manager = new WebSocketManager<TClientMsg, TServerMsg>({
  url,
  serialize: (msg) => JSON.stringify(msg),
  deserialize: (raw) => JSON.parse(raw),
});

useSocketEvent(manager, "echo", (msg) => {
  // msg narrowed to the "echo" variant of TServerMsg
});

const { send } = useSocketSend(manager);
send({ type: "ecoh", text: "hi" }); // compile error on the typo

Subscriptions without the bookkeeping

Anything beyond a chat demo eventually needs many components reading the same stream: ten price tickers for the same symbol, two avatars and a header all watching the same presence channel. With a raw hook you either lift state and share, or you accept that subscribes and unsubscribes fire per mount, which floods the server.

react-socket ref counts subscriptions by a stable key. The subscribe payload goes out on the first mount. The unsubscribe fires on the last unmount. Five components, one server message. Reconnect and every active subscription restores itself without you writing any code.

When to pick react-use-websocket

When to pick react-socket

Next steps