Socket.IO in React Native

Socket.IO is useful when a React Native app needs low-latency, bidirectional communication: chat, typing indicators, live order status, dispatch dashboards, presence, auctions, multiplayer interactions, or collaborative workflows.
The important production detail is lifecycle. Mobile apps disconnect, reconnect, background, resume, rotate networks, and refresh auth tokens. A reliable Socket.IO integration handles those cases instead of creating one global socket that lives forever.
Quick Answer
Install socket.io-client, create the socket in a small service or hook, pass
auth during connection, subscribe to events in useEffect, remove listeners on
cleanup, and design the backend so missed events can be recovered from durable
storage.
corepack yarn add socket.io-client
Socket.IO is a transport for realtime events. For Instamobile apps that already ship Firebase chat, review the Chat Module and Firebase chat schema before adding a custom Socket.IO server.
When Socket.IO Is a Good Fit
Use Socket.IO when the app needs:
- realtime events from your own Node.js backend;
- reconnect behavior across unstable mobile networks;
- a request/response API plus event streams;
- rooms for channels, trips, orders, or live sessions;
- fallback behavior when a pure WebSocket connection is unavailable.
Do not use Socket.IO only to fetch ordinary lists. For standard CRUD screens, HTTP APIs, Firebase listeners, or GraphQL subscriptions may be simpler.
Install the Client
In a current Yarn/Corepack project:
corepack yarn add socket.io-client
If you use TypeScript, the package includes its own types. Avoid installing old
@types/socket.io-client packages unless a specific legacy app requires them.
Create a Typed Socket Client
Keep event names and payloads typed:
import { io, Socket } from 'socket.io-client';
type ServerToClientEvents = {
'message:new': (message: ChatMessage) => void;
'typing:update': (payload: { channelId: string; userId: string }) => void;
'connect_error': (error: Error) => void;
};
type ClientToServerEvents = {
'message:send': (
payload: { channelId: string; text: string },
ack: (result: { ok: boolean; messageId?: string; error?: string }) => void
) => void;
'typing:start': (payload: { channelId: string }) => void;
};
export function createChatSocket(token: string): Socket<ServerToClientEvents, ClientToServerEvents> {
return io('https://api.example.com/chat', {
auth: { token },
transports: ['websocket'],
autoConnect: false,
});
}
Use your production API host. localhost from a simulator or physical device
does not always point to your development machine.
Mega Bundle Sale is ON! Get ALL of our React Native codebases at 90% OFF discount 🔥
Get the Mega BundleConnect From a Hook
Create and clean up the socket with the screen or provider that owns it:
import { useEffect, useMemo, useState } from 'react';
import type { Socket } from 'socket.io-client';
import { createChatSocket } from './createChatSocket';
export function useChatSocket(token: string | null) {
const [connected, setConnected] = useState(false);
const socket = useMemo(() => {
if (!token) return null;
return createChatSocket(token);
}, [token]);
useEffect(() => {
if (!socket) return;
function handleConnect() {
setConnected(true);
}
function handleDisconnect() {
setConnected(false);
}
socket.on('connect', handleConnect);
socket.on('disconnect', handleDisconnect);
socket.connect();
return () => {
socket.off('connect', handleConnect);
socket.off('disconnect', handleDisconnect);
socket.disconnect();
};
}, [socket]);
return { socket, connected };
}
This avoids duplicate event listeners when a screen remounts.
Subscribe to Messages Safely
Use functional state updates so event handlers do not close over stale arrays:
import { useEffect, useState } from 'react';
export function useLiveMessages(socket: ChatSocket | null, channelId: string) {
const [messages, setMessages] = useState<ChatMessage[]>([]);
useEffect(() => {
if (!socket) return;
function handleMessage(message: ChatMessage) {
if (message.channelId !== channelId) return;
setMessages((current) => [...current, message]);
}
socket.emit('channel:join', { channelId });
socket.on('message:new', handleMessage);
return () => {
socket.off('message:new', handleMessage);
socket.emit('channel:leave', { channelId });
};
}, [socket, channelId]);
return messages;
}
For real chat, the socket event should be a notification that new data exists. Store messages in a database and fetch missing history when the app reconnects.
Handle Auth and Reconnection
Mobile sockets need clear auth behavior:
- pass access tokens in the Socket.IO
authoption, not in hardcoded URLs; - refresh tokens before reconnecting when possible;
- reject unauthorized sockets on the server;
- leave rooms when a user logs out;
- reconnect with exponential backoff defaults unless your product needs a custom strategy;
- show offline UI when the socket is disconnected.
If your app uses Firebase Auth, mint a backend session token or verify Firebase ID tokens server-side. Do not trust a user ID sent by the client as proof of identity.
Production Checklist
Before shipping a Socket.IO feature:
- events are typed and documented;
- server and client Socket.IO major versions are compatible;
- every listener is removed on cleanup;
- app background/resume behavior is tested;
- missed events are recoverable from storage;
- auth failure logs out or reauthenticates cleanly;
- rooms are scoped by permissions;
- rate limits protect high-frequency events like typing and location;
- release builds are tested on real devices.
If your app already uses Instamobile Firebase chat, compare this with the Chat Module before adding another realtime provider.
Looking for a custom mobile application?
Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.
Get in TouchFAQ
Is Socket.IO the same as WebSocket?
No. Socket.IO can use WebSocket, but it adds its own protocol, fallbacks, rooms, reconnection behavior, acknowledgements, and server/client APIs.
Can a React Native app connect to localhost?
Only in specific simulator setups. Physical devices and Android emulators often need a LAN IP, emulator host alias, tunnel, or real HTTPS development backend.
Should chat messages live only in Socket.IO events?
No. Store messages durably in your backend. Use Socket.IO for realtime delivery and use the database/API to recover missed messages after reconnect.