A SignalR Connection Pool for React Native
Realtime on mobile looks easy in demos: open a connection, subscribe, done. Real apps need several live hubs at once — one for orders, one for chat, one for presence — and phones are hostile to sockets. Networks flip from Wi-Fi to cellular, the OS suspends the app, and every connection you thought you had is gone.
The pattern that has served me well is a small connection pool behind a React hook.
The shape
A single module owns a registry of named connections, held in a ref so re-renders never touch it:
const pool = useRef({}) // { orders: {conn, listeners}, chat: {...} }
Each entry carries its own listener map, its own config, and its own retry policy. Components ask for a hub by name; the pool creates it on first use and reuses it afterwards.
Three details make it production-grade:
1. A fixed, boring retry delay. Exponential backoff sounds smart, but for a foreground mobile app a flat "retry every 5 seconds" is more predictable and easier to reason about:
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: () => 5000,
})
2. Connection state mirrored into React. Each hub's status lives in state, keyed by name. The UI can show "reconnecting…" per feature instead of one global mystery spinner. Users forgive a banner; they don't forgive a frozen screen.
3. A manual reconnect that knows when to do nothing. The subtle bug: the user taps "retry" while the library's own reconnect loop is mid-flight, and now two loops fight over one socket. The pool's manualReconnect deliberately no-ops if an automatic retry is already running.
The takeaway
The pool is maybe two hundred lines. The value isn't clever code — it's that every screen in the app gets realtime with the same guarantees, and connection chaos is handled in exactly one place. On mobile, whatever can go wrong with a socket, will. Centralize the pain.
Enjoyed this post?
Subscribe to the newsletter
Get future posts delivered to your inbox. No spam, unsubscribe anytime.