๐ WebSocket in React Native
Real-Time Communication Made Simple
๐ The Magic Bridge Analogy
Imagine you have a walkie-talkie with your best friend. Once you turn it on and connect, you can both talk and listen at the same time, without hanging up and calling again.
Thatโs exactly what a WebSocket is! Itโs like a walkie-talkie for your app and a server.
Regular HTTP (like a phone call):
- You call โ Server answers โ You hang up
- Need to talk again? Call again! ๐
WebSocket (like a walkie-talkie):
- Connect once โ Talk anytime โ Listen anytime ๐ป
- No need to reconnect!
๐ก What is WebSocket?
WebSocket is a communication protocol that creates a persistent, two-way connection between your React Native app and a server.
Why is this amazing?
| Feature | HTTP (Old Way) | WebSocket (Cool Way) |
|---|---|---|
| Connection | Open โ Close โ Open | Stay Open Forever |
| Who Talks First? | Only Client | Both! |
| Speed | Slower | Super Fast |
| Real-time? | Nope | Yes! |
Real Examples:
- ๐ฌ Chat apps (WhatsApp, Messenger)
- ๐ฎ Online games
- ๐ Stock price updates
- ๐ Live notifications
๐ WebSocket Connection
How to Create Your Walkie-Talkie
Think of connecting a WebSocket like this:
- ๐ Dial the number (create connection)
- ๐ณ Wait for pickup (connection opens)
- ๐ฃ๏ธ Start talking (send messages)
- ๐ Listen (receive messages)
- ๐ด Hang up when done (close connection)
๐ ๏ธ Creating a WebSocket Connection
// Create your walkie-talkie!
const ws = new WebSocket('wss://example.com/socket');
// When connection opens (friend picked up!)
ws.onopen = () => {
console.log('Connected! ๐');
};
// When you receive a message
ws.onmessage = (event) => {
console.log('Got message:', event.data);
};
Breaking It Down:
new WebSocket(url) - Creates the connection
ws://= Not secure (like shouting in public)wss://= Secure (like whispering privately) โ
onopen - Runs when connected successfully
onmessage - Runs when server sends you something
๐ค Sending Messages
// Make sure connection is open first!
if (ws.readyState === WebSocket.OPEN) {
ws.send('Hello Server!');
// Send JSON data (most common)
ws.send(JSON.stringify({
type: 'chat',
message: 'Hi there!'
}));
}
The readyState Values:
| Value | Meaning | Analogy |
|---|---|---|
| 0 | CONNECTING | Phone is ringingโฆ |
| 1 | OPEN | Friend answered! โ |
| 2 | CLOSING | Saying goodbyeโฆ |
| 3 | CLOSED | Hung up |
๐จ Handling Errors & Closing
// When something goes wrong
ws.onerror = (error) => {
console.log('Oops! Error:', error);
};
// When connection closes
ws.onclose = (event) => {
console.log('Connection closed');
console.log('Code:', event.code);
console.log('Reason:', event.reason);
};
// To close the connection yourself
ws.close();
๐ Complete Connection Example
import { useEffect, useState } from 'react';
function ChatComponent() {
const [socket, setSocket] = useState(null);
const [messages, setMessages] = useState([]);
useEffect(() => {
// Create connection
const ws = new WebSocket('wss://chat.example.com');
ws.onopen = () => {
console.log('Connected!');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
setMessages(prev => [...prev, data]);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
setSocket(ws);
// Cleanup when component unmounts
return () => ws.close();
}, []);
return (/* your UI */);
}
๐จ WebSocket Patterns
Smart Ways to Use WebSockets
Now that you know how to connect, letโs learn the patterns - the smart ways to use WebSockets in real apps!
๐ Pattern 1: Reconnection Pattern
The Problem: What if your internet drops? Your walkie-talkie disconnects!
The Solution: Auto-reconnect! Keep trying to connect again.
graph TD A["Connected"] -->|Internet drops| B["Disconnected"] B --> C{Wait 2 seconds} C --> D["Try to Reconnect"] D -->|Success| A D -->|Fail| C
Code Example:
function createWebSocket() {
const ws = new WebSocket('wss://example.com');
ws.onclose = () => {
console.log('Disconnected! Reconnecting...');
// Wait 3 seconds, then try again
setTimeout(createWebSocket, 3000);
};
return ws;
}
const socket = createWebSocket();
Better Version with Limits:
let retryCount = 0;
const MAX_RETRIES = 5;
function connectWithRetry() {
if (retryCount >= MAX_RETRIES) {
console.log('Too many failures. Giving up.');
return;
}
const ws = new WebSocket('wss://example.com');
ws.onopen = () => {
retryCount = 0; // Reset on success!
};
ws.onclose = () => {
retryCount++;
const delay = Math.min(1000 * retryCount, 10000);
setTimeout(connectWithRetry, delay);
};
}
๐ Pattern 2: Heartbeat Pattern
The Problem: How do you know if the connection is still alive? Sometimes it justโฆ dies silently.
The Solution: Send a โpingโ every few seconds. Like saying โAre you still there?โ
graph LR A["App"] -->|Ping every 30s| B["Server"] B -->|Pong| A A -->|No Pong?| C["Reconnect!"]
Code Example:
let heartbeatInterval;
function startHeartbeat(ws) {
heartbeatInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping' }));
}
}, 30000); // Every 30 seconds
}
function stopHeartbeat() {
clearInterval(heartbeatInterval);
}
// Usage
ws.onopen = () => startHeartbeat(ws);
ws.onclose = () => stopHeartbeat();
๐ฌ Pattern 3: Message Queue Pattern
The Problem: What if you try to send a message but youโre not connected yet?
The Solution: Save messages in a queue, send them when connected!
const messageQueue = [];
function sendMessage(ws, message) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(message));
} else {
// Save for later!
messageQueue.push(message);
}
}
// When connection opens, send queued messages
ws.onopen = () => {
while (messageQueue.length > 0) {
const msg = messageQueue.shift();
ws.send(JSON.stringify(msg));
}
};
๐ท๏ธ Pattern 4: Message Types Pattern
The Problem: Different messages need different handling. How do you organize them?
The Solution: Use a type field and a message handler!
Message Structure:
// Every message looks like this:
{
type: 'chat_message', // What kind?
payload: { // The actual data
text: 'Hello!',
sender: 'Alice'
}
}
Handler Pattern:
const handlers = {
chat_message: (payload) => {
addMessageToChat(payload);
},
user_joined: (payload) => {
showNotification(`${payload.name} joined!`);
},
typing: (payload) => {
showTypingIndicator(payload.user);
}
};
ws.onmessage = (event) => {
const { type, payload } = JSON.parse(event.data);
if (handlers[type]) {
handlers[type](payload);
} else {
console.warn('Unknown message type:', type);
}
};
๐ฏ Pattern 5: Room/Channel Pattern
The Problem: In a chat app, how do you send messages to specific groups?
The Solution: Join โroomsโ or โchannelsโ!
graph TD A["User"] -->|Join| B["Room: Gaming"] A -->|Join| C["Room: Music"] D["Other User"] -->|Join| B B -->|Message| A B -->|Message| D
Code Example:
// Join a room
function joinRoom(ws, roomId) {
ws.send(JSON.stringify({
type: 'join_room',
payload: { roomId }
}));
}
// Leave a room
function leaveRoom(ws, roomId) {
ws.send(JSON.stringify({
type: 'leave_room',
payload: { roomId }
}));
}
// Send to specific room
function sendToRoom(ws, roomId, message) {
ws.send(JSON.stringify({
type: 'room_message',
payload: { roomId, message }
}));
}
๐ Pattern 6: Authentication Pattern
The Problem: How does the server know who you are?
The Solution: Send your token when connecting!
// Method 1: URL parameter
const token = 'your-auth-token';
const ws = new WebSocket(
`wss://example.com?token=${token}`
);
// Method 2: First message after connecting
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'authenticate',
payload: { token: 'your-auth-token' }
}));
};
๐งน Complete React Native Hook
Hereโs everything together in a reusable hook:
import { useEffect, useRef, useState } from 'react';
export function useWebSocket(url) {
const [isConnected, setIsConnected] = useState(false);
const [lastMessage, setLastMessage] = useState(null);
const wsRef = useRef(null);
const retryCount = useRef(0);
const connect = () => {
const ws = new WebSocket(url);
ws.onopen = () => {
setIsConnected(true);
retryCount.current = 0;
};
ws.onmessage = (event) => {
setLastMessage(JSON.parse(event.data));
};
ws.onclose = () => {
setIsConnected(false);
// Auto-reconnect
const delay = Math.min(
1000 * Math.pow(2, retryCount.current),
30000
);
retryCount.current++;
setTimeout(connect, delay);
};
wsRef.current = ws;
};
const send = (data) => {
if (wsRef.current?.readyState === 1) {
wsRef.current.send(JSON.stringify(data));
}
};
useEffect(() => {
connect();
return () => wsRef.current?.close();
}, [url]);
return { isConnected, lastMessage, send };
}
Usage:
function ChatScreen() {
const { isConnected, lastMessage, send } =
useWebSocket('wss://chat.example.com');
return (
<View>
<Text>
{isConnected ? '๐ข Online' : '๐ด Offline'}
</Text>
<Button
title="Say Hi!"
onPress={() => send({ text: 'Hello!' })}
/>
</View>
);
}
๐ Summary
You learned two big things today:
1. WebSocket Connection
- Create with
new WebSocket(url) - Use
wss://for security - Handle
onopen,onmessage,onerror,onclose - Check
readyStatebefore sending
2. WebSocket Patterns
- ๐ Reconnection - Auto-connect when disconnected
- ๐ Heartbeat - Check if connection is alive
- ๐ฌ Message Queue - Save messages for later
- ๐ท๏ธ Message Types - Organize with type handlers
- ๐ฏ Rooms/Channels - Group communication
- ๐ Authentication - Identify users
๐ก Quick Tips
- Always use
wss://(notws://) in production - Always clean up in Reactโs
useEffectreturn - Always handle errors - connections fail!
- Use JSON for complex data
- Add reconnection - networks are unreliable
Now go build something amazing with real-time features! ๐
