Skip to main content

Socket.IO in React Native

· 5 min read
Full Stack Developer
Last updated on May 17, 2026

react native socketio

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 Bundle

Connect 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 auth option, 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 Touch

FAQ

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.