React Native y WebSockets: Comunicación en Tiempo Real con `ws` y `Socket.IO`
Este tutorial te guiará a través de la implementación de comunicación en tiempo real en tus aplicaciones React Native utilizando WebSockets. Exploraremos tanto la API nativa `ws` como la popular librería `Socket.IO` para conectar tu frontend móvil con un backend en tiempo real. Aprenderás a configurar el servidor y el cliente, enviar y recibir mensajes, y manejar eventos.
La comunicación en tiempo real es una característica fundamental para muchas aplicaciones modernas, desde chats hasta paneles de control interactivos y juegos. En el ecosistema de React Native, los WebSockets ofrecen una solución eficiente y bidireccional para lograr esta interactividad.
Este tutorial te sumergirá en el mundo de los WebSockets con React Native. Cubriremos dos enfoques principales: la API nativa de WebSockets (ws) y la librería Socket.IO, conocida por su robustez y características adicionales como la reconexión automática y el fallback a HTTP long-polling.
🚀 ¿Qué son los WebSockets?
Los WebSockets son un protocolo de comunicación que proporciona un canal de comunicación dúplex completo sobre una única conexión TCP. A diferencia de HTTP, que es unidireccional (cliente envía una petición, servidor responde), los WebSockets permiten que tanto el cliente como el servidor envíen datos de forma independiente en cualquier momento, una vez establecida la conexión. Esto los hace ideales para aplicaciones que requieren actualizaciones instantáneas.
Ventajas de los WebSockets:
- Bidireccionalidad: Permiten el flujo de datos en ambas direcciones simultáneamente.
- Baja latencia: Una vez establecida la conexión, los datos se envían sin la sobrecarga de los encabezados HTTP repetitivos.
- Eficiencia: Menos consumo de recursos de red en comparación con el polling constante.
- Persistencia: La conexión se mantiene abierta, eliminando la necesidad de reestablecerla para cada intercambio de datos.
🛠️ Configuración Inicial: Servidor y Cliente
Antes de sumergirnos en el código de React Native, necesitamos un servidor de WebSockets básico con el que nuestro cliente pueda interactuar. Usaremos Node.js para el servidor debido a su popularidad y facilidad de uso con librerías como ws y Socket.IO.
1. Preparando el Entorno de Desarrollo
Asegúrate de tener Node.js y npm (o yarn) instalados en tu sistema. Para el cliente React Native, necesitarás un entorno de desarrollo React Native funcional (Expo CLI o React Native CLI).
# Verifica Node.js y npm
node -v
npm -v
# Crea un nuevo proyecto React Native (si no tienes uno)
npx react-native init RealtimeApp
cd RealtimeApp
# O si prefieres Expo
npx create-expo-app RealtimeAppExpo
cd RealtimeAppExpo
🌐 Implementando WebSockets con la API Nativa (ws)
Empezaremos con la implementación más básica utilizando la API de WebSockets disponible tanto en navegadores como en React Native, y un servidor Node.js que usa la librería ws.
Servidor ws (Node.js)
Crea una nueva carpeta llamada server en la raíz de tu proyecto o en una ubicación separada. Dentro de server, inicializa un proyecto Node.js y instala la librería ws.
mkdir server
cd server
npm init -y
npm install ws
Crea un archivo index.js dentro de la carpeta server con el siguiente contenido:
// server/index.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
console.log('Cliente conectado');
ws.on('message', message => {
console.log(`Mensaje recibido: ${message}`);
// Envía el mensaje de vuelta a todos los clientes conectados
wss.clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(`Eco de ${message}`);
}
});
// Envía un mensaje solo al cliente que lo envió
ws.send(`Recibiste: ${message}`);
});
ws.on('close', () => {
console.log('Cliente desconectado');
});
ws.on('error', error => {
console.error('WebSocket error:', error);
});
ws.send('Bienvenido al servidor WebSocket nativo!');
});
console.log('Servidor WebSocket nativo iniciado en ws://localhost:8080');
Inicia el servidor:
node server/index.js
Cliente React Native (ws)
En tu proyecto React Native, el objeto global WebSocket ya está disponible. No necesitas instalar librerías adicionales para el cliente nativo.
Modifica tu archivo App.js (o App.tsx si usas TypeScript) para incluir el cliente WebSocket.
// App.js
import React, { useEffect, useState } from 'react';
import { SafeAreaView, Text, TextInput, Button, FlatList, View, StyleSheet } from 'react-native';
const WS_URL = 'ws://localhost:8080'; // Asegúrate de que esta URL sea accesible desde tu dispositivo/emulador
const App = () => {
const [socket, setSocket] = useState(null);
const [message, setMessage] = useState('');
const [messages, setMessages] = useState([]);
useEffect(() => {
const ws = new WebSocket(WS_URL);
ws.onopen = () => {
console.log('Conectado al servidor WebSocket nativo');
setMessages(prev => [...prev, { id: Date.now(), text: 'Conectado al servidor.', type: 'system' }]);
};
ws.onmessage = (event) => {
console.log('Mensaje recibido del servidor:', event.data);
setMessages(prev => [...prev, { id: Date.now(), text: event.data, type: 'server' }]);
};
ws.onerror = (error) => {
console.error('Error del WebSocket:', error);
setMessages(prev => [...prev, { id: Date.now(), text: `Error: ${error.message}`, type: 'error' }]);
};
ws.onclose = () => {
console.log('Desconectado del servidor WebSocket nativo');
setMessages(prev => [...prev, { id: Date.now(), text: 'Desconectado del servidor.', type: 'system' }]);
// Opcional: intentar reconectar
// setTimeout(() => setSocket(new WebSocket(WS_URL)), 3000);
};
setSocket(ws);
return () => {
if (ws.readyState === WebSocket.OPEN) {
ws.close();
}
};
}, []);
const sendMessage = () => {
if (socket && socket.readyState === WebSocket.OPEN && message.trim()) {
socket.send(message.trim());
setMessages(prev => [...prev, { id: Date.now(), text: `Yo: ${message.trim()}`, type: 'client' }]);
setMessage('');
}
};
const renderMessage = ({ item }) => (
<View style={styles.messageContainer}>
<Text style={[styles.messageText, styles[item.type]]}>{item.text}</Text>
</View>
);
return (
<SafeAreaView style={styles.container}>
<Text style={styles.header}>React Native WebSocket Nativo</Text>
<FlatList
data={messages}
renderItem={renderMessage}
keyExtractor={(item) => item.id.toString()}
style={styles.messageList}
inverted // Para mostrar los mensajes más recientes abajo
/>
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
value={message}
onChangeText={setMessage}
placeholder="Escribe un mensaje..."
placeholderTextColor="#999"
/>
<Button title="Enviar" onPress={sendMessage} disabled={!socket || socket.readyState !== WebSocket.OPEN} />
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f2f5',
paddingTop: 20,
},
header: {
fontSize: 22,
fontWeight: 'bold',
textAlign: 'center',
marginVertical: 15,
color: '#333',
},
messageList: {
flex: 1,
paddingHorizontal: 10,
},
messageContainer: {
paddingVertical: 5,
},
messageText: {
fontSize: 16,
padding: 8,
borderRadius: 10,
marginBottom: 5,
maxWidth: '80%',
},
system: {
alignSelf: 'center',
backgroundColor: '#e0e0e0',
color: '#555',
textAlign: 'center',
},
server: {
alignSelf: 'flex-start',
backgroundColor: '#dcf8c6',
color: '#333',
},
client: {
alignSelf: 'flex-end',
backgroundColor: '#add8e6',
color: '#333',
},
error: {
alignSelf: 'center',
backgroundColor: '#ffdddd',
color: '#cc0000',
},
inputContainer: {
flexDirection: 'row',
padding: 10,
borderTopWidth: 1,
borderTopColor: '#ccc',
backgroundColor: '#fff',
},
input: {
flex: 1,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 20,
paddingHorizontal: 15,
marginRight: 10,
fontSize: 16,
color: '#333',
},
});
export default App;
✨ Mejorando con Socket.IO
Aunque la API nativa ws es funcional, Socket.IO es una librería popular que ofrece una capa de abstracción sobre WebSockets, añadiendo características como:
- Reconexión automática.
- Detección de desconexiones.
- Fallback a HTTP long-polling si WebSockets no están disponibles.
- Envío de eventos personalizados.
- Manejo de namespaces y rooms para una mejor organización.
Servidor Socket.IO (Node.js)
En tu carpeta server, instala socket.io y cors (para evitar problemas de CORS).
npm install socket.io cors
Modifica server/index.js o crea un nuevo archivo server/socketio-server.js:
// server/socketio-server.js
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const cors = require('cors');
const app = express();
app.use(cors()); // Habilita CORS para todas las rutas
const server = http.createServer(app);
// Configura Socket.IO
const io = new Server(server, {
cors: {
origin: "*", // Permite conexiones desde cualquier origen
methods: ["GET", "POST"]
}
});
io.on('connection', (socket) => {
console.log(`Usuario conectado: ${socket.id}`);
// Emitir un mensaje de bienvenida solo al cliente que se conectó
socket.emit('welcome', `Bienvenido al servidor Socket.IO, ${socket.id}!`);
// Manejar el evento 'chat message' del cliente
socket.on('chat message', (msg) => {
console.log(`Mensaje de ${socket.id}: ${msg}`);
// Emitir el mensaje a todos los clientes conectados, excepto al que lo envió
socket.broadcast.emit('chat message', { id: socket.id, message: msg });
// Emitir el mensaje de vuelta al cliente que lo envió (para confirmación local)
socket.emit('my message', { id: socket.id, message: msg });
});
// Manejar el evento 'disconnect'
socket.on('disconnect', () => {
console.log(`Usuario desconectado: ${socket.id}`);
// Notificar a todos los demás clientes que un usuario se ha desconectado
io.emit('system message', `Usuario ${socket.id} se ha desconectado.`);
});
// Enviar un mensaje del sistema a todos los usuarios cuando alguien se conecta
socket.broadcast.emit('system message', `Usuario ${socket.id} se ha conectado.`);
});
const PORT = 3000;
server.listen(PORT, () => {
console.log(`Servidor Socket.IO escuchando en http://localhost:${PORT}`);
});
Inicia este servidor:
node server/socketio-server.js
Cliente React Native (Socket.IO)
Para el cliente React Native, usaremos la librería socket.io-client.
cd RealtimeApp # o RealtimeAppExpo
npm install socket.io-client
# Para Expo, es posible que necesites instalar algunas dependencias para el cliente HTTP subyacente
# npx expo install @react-native-async-storage/async-storage # ejemplo si encuentras errores
Ahora, actualiza App.js para usar socket.io-client.
// App.js (versión Socket.IO)
import React, { useEffect, useState, useRef } from 'react';
import { SafeAreaView, Text, TextInput, Button, FlatList, View, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
import io from 'socket.io-client';
const SOCKET_URL = 'http://localhost:3000'; // Asegúrate de que esta URL sea accesible
const App = () => {
const [socket, setSocket] = useState(null);
const [message, setMessage] = useState('');
const [messages, setMessages] = useState([]);
const flatListRef = useRef(null);
useEffect(() => {
const newSocket = io(SOCKET_URL, {
transports: ['websocket'], // Forzar el uso de WebSockets en RN
forceNew: true, // Para asegurar una nueva conexión cada vez que se monta
});
newSocket.on('connect', () => {
console.log('Conectado a Socket.IO. ID:', newSocket.id);
setMessages(prev => [...prev, { id: Date.now(), text: `Conectado al servidor. ID: ${newSocket.id}`, type: 'system' }]);
});
newSocket.on('welcome', (msg) => {
setMessages(prev => [...prev, { id: Date.now(), text: msg, type: 'server' }]);
});
newSocket.on('chat message', (data) => {
// Recibido de otros usuarios
setMessages(prev => [...prev, { id: Date.now(), text: `Usuario ${data.id.substring(0, 4)}: ${data.message}`, type: 'other' }]);
});
newSocket.on('my message', (data) => {
// Confirmación de mi propio mensaje enviado
setMessages(prev => [...prev, { id: Date.now(), text: `Yo: ${data.message}`, type: 'client' }]);
});
newSocket.on('system message', (msg) => {
setMessages(prev => [...prev, { id: Date.now(), text: msg, type: 'system' }]);
});
newSocket.on('disconnect', () => {
console.log('Desconectado de Socket.IO');
setMessages(prev => [...prev, { id: Date.now(), text: 'Desconectado del servidor.', type: 'system' }]);
});
newSocket.on('connect_error', (err) => {
console.error('Error de conexión Socket.IO:', err.message);
setMessages(prev => [...prev, { id: Date.now(), text: `Error de conexión: ${err.message}`, type: 'error' }]);
});
setSocket(newSocket);
return () => {
newSocket.disconnect();
};
}, []);
useEffect(() => {
if (flatListRef.current) {
flatListRef.current.scrollToEnd({ animated: true });
}
}, [messages]);
const sendMessage = () => {
if (socket && message.trim()) {
socket.emit('chat message', message.trim());
setMessage('');
}
};
const renderMessage = ({ item }) => {
let messageStyle;
switch (item.type) {
case 'system':
messageStyle = styles.system;
break;
case 'server':
messageStyle = styles.server;
break;
case 'client':
messageStyle = styles.client;
break;
case 'other':
messageStyle = styles.other;
break;
case 'error':
messageStyle = styles.error;
break;
default:
messageStyle = styles.system;
}
return (
<View style={styles.messageContainer}>
<Text style={[styles.messageText, messageStyle]}>{item.text}</Text>
</View>
);
};
return (
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={{ flex: 1 }}
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}
>
<Text style={styles.header}>React Native Socket.IO Chat</Text>
<FlatList
ref={flatListRef}
data={messages}
renderItem={renderMessage}
keyExtractor={(item) => item.id.toString()}
style={styles.messageList}
contentContainerStyle={{ paddingBottom: 10 }}
/>
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
value={message}
onChangeText={setMessage}
placeholder="Escribe un mensaje..."
placeholderTextColor="#999"
editable={socket && socket.connected}
/>
<Button title="Enviar" onPress={sendMessage} disabled={!socket || !socket.connected || !message.trim()} />
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f2f5',
paddingTop: 20,
},
header: {
fontSize: 22,
fontWeight: 'bold',
textAlign: 'center',
marginVertical: 15,
color: '#333',
},
messageList: {
flex: 1,
paddingHorizontal: 10,
},
messageContainer: {
paddingVertical: 5,
},
messageText: {
fontSize: 16,
padding: 8,
borderRadius: 10,
marginBottom: 5,
maxWidth: '80%',
},
system: {
alignSelf: 'center',
backgroundColor: '#e0e0e0',
color: '#555',
textAlign: 'center',
},
server: {
alignSelf: 'flex-start',
backgroundColor: '#dcf8c6',
color: '#333',
},
client: {
alignSelf: 'flex-end',
backgroundColor: '#add8e6',
color: '#333',
},
other: {
alignSelf: 'flex-start',
backgroundColor: '#fff',
color: '#333',
borderColor: '#ddd',
borderWidth: 1,
},
error: {
alignSelf: 'center',
backgroundColor: '#ffdddd',
color: '#cc0000',
},
inputContainer: {
flexDirection: 'row',
padding: 10,
borderTopWidth: 1,
borderTopColor: '#ccc',
backgroundColor: '#fff',
},
input: {
flex: 1,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 20,
paddingHorizontal: 15,
marginRight: 10,
fontSize: 16,
color: '#333',
},
});
export default App;
🔍 Comparativa entre ws y Socket.IO
Ambas opciones son válidas, pero tienen sus casos de uso. Aquí una tabla comparativa:
| Característica | WebSocket (API nativa/ws) | Socket.IO |
|---|---|---|
| --- | --- | --- |
| Complejidad | Más bajo nivel, requiere más manejo manual | Más alto nivel, abstrae detalles de la conexión |
| Fiabilidad | Requiere manejo manual de reconexión, fallos | Reconexión automática, detección de desconexión |
| --- | --- | --- |
| Fallback | Solo WebSockets | WebSockets, HTTP Long Polling, etc. |
| API | onopen, onmessage, onerror, onclose, send | on, emit, namespaces, rooms |
| --- | --- | --- |
| Eventos Personalizados | No directamente, requiere serialización manual | Sí, con emit/on |
| Sobrecarga | Más ligero | Ligeramente más sobrecarga por las características adicionales |
| --- | --- | --- |
| Uso | Aplicaciones sencillas, control granular | Aplicaciones complejas, chats, juegos, colaboración en tiempo real |
📈 Casos de Uso Comunes
Los WebSockets en React Native abren un mundo de posibilidades para la interactividad en tus aplicaciones:
- Aplicaciones de Chat: La transmisión instantánea de mensajes es el caso de uso más obvio.
- Notificaciones en Tiempo Real: Envía notificaciones a los usuarios sin necesidad de polling.
- Juegos Multijugador: Sincroniza estados de juego entre jugadores.
- Paneles de Control: Actualiza gráficos y datos en tiempo real para monitorización.
- Colaboración: Edición conjunta de documentos, pizarras interactivas.
- Streaming de Datos: Acciones de bolsa, resultados deportivos en vivo.
🔒 Consideraciones de Seguridad
Al trabajar con WebSockets, la seguridad es clave:
- WSS (WebSocket Secure): Siempre usa
wss://en producción. Esto cifra la comunicación a través de TLS/SSL, al igual que HTTPS. - Autenticación y Autorización: Implementa mecanismos para asegurar que solo los usuarios autorizados puedan conectarse y enviar/recibir mensajes. Esto puede hacerse con tokens JWT enviados durante el handshake inicial o a través de los mensajes.
- Validación de Entrada: Valida todos los mensajes recibidos del cliente en el servidor para prevenir ataques como inyección de código o desbordamiento de búfer.
- Rate Limiting: Limita la cantidad de mensajes que un cliente puede enviar en un período de tiempo para prevenir ataques DoS.
💡 Ejemplos Avanzados y Patrones
Manejo de Estados con Context API o Redux
En aplicaciones más complejas, es útil integrar los mensajes de WebSocket con tu sistema de gestión de estado global (Context API, Redux, Zustand, etc.). Puedes despachar acciones o actualizar el estado directamente desde tus listeners de onmessage o socket.on.
// Ejemplo simplificado con Context API
// Context/SocketContext.js
import React, { createContext, useContext, useEffect, useState } from 'react';
import io from 'socket.io-client';
const SocketContext = createContext();
export const useSocket = () => useContext(SocketContext);
export const SocketProvider = ({ children }) => {
const [socket, setSocket] = useState(null);
const [isSocketConnected, setIsSocketConnected] = useState(false);
const [receivedMessages, setReceivedMessages] = useState([]);
useEffect(() => {
const newSocket = io('http://localhost:3000', { transports: ['websocket'] });
newSocket.on('connect', () => {
setIsSocketConnected(true);
console.log('Socket Context: Conectado');
});
newSocket.on('disconnect', () => {
setIsSocketConnected(false);
console.log('Socket Context: Desconectado');
});
newSocket.on('chat message', (data) => {
setReceivedMessages(prev => [...prev, { id: Date.now(), text: `Otro: ${data.message}`, type: 'other' }]);
});
setSocket(newSocket);
return () => {
newSocket.disconnect();
};
}, []);
const sendMessage = (msg) => {
if (socket && isSocketConnected) {
socket.emit('chat message', msg);
setReceivedMessages(prev => [...prev, { id: Date.now(), text: `Yo: ${msg}`, type: 'client' }]);
}
};
return (
<SocketContext.Provider value={{ socket, isSocketConnected, receivedMessages, sendMessage }}>
{children}
</SocketContext.Provider>
);
};
// En tu App.js (o un componente hijo)
// <SocketProvider>
// <YourChatComponent />
// </SocketProvider>
// Dentro de YourChatComponent
// const { isSocketConnected, receivedMessages, sendMessage } = useSocket();
// ... UI con mensajes y función sendMessage
Usando Rooms y Namespaces (Socket.IO)
¿Qué son las *Rooms* y *Namespaces*?
Socket.IO permite organizar tus conexiones con *namespaces* (rutas lógicas para dividir la aplicación, ej. `/admin`, `/chat`) y *rooms* (grupos de sockets dentro de un *namespace*, ej. `room1`, `general`). Esto es útil para escalar y gestionar eventos específicos para subconjuntos de usuarios. Por ejemplo, en un chat, cada conversación podría ser una *room* diferente.Ejemplo de Servidor con Rooms (Socket.IO):
// server/socketio-rooms-server.js
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const cors = require('cors');
const app = express();
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
io.on('connection', (socket) => {
console.log(`Usuario conectado: ${socket.id}`);
socket.on('joinRoom', (roomName) => {
// Dejar cualquier sala anterior y unirse a la nueva
socket.rooms.forEach(room => {
if (room !== socket.id) { // socket.id es la sala predeterminada de cada socket
socket.leave(room);
console.log(`Usuario ${socket.id} ha dejado la sala ${room}`);
}
});
socket.join(roomName);
console.log(`Usuario ${socket.id} se ha unido a la sala ${roomName}`);
io.to(roomName).emit('system message', `Usuario ${socket.id} se ha unido a ${roomName}.`);
socket.emit('joinedRoom', roomName);
});
socket.on('roomMessage', ({ room, message }) => {
console.log(`Mensaje en sala ${room} de ${socket.id}: ${message}`);
io.to(room).emit('roomMessage', { id: socket.id, room: room, message: message });
});
socket.on('disconnect', () => {
console.log(`Usuario desconectado: ${socket.id}`);
// Al desconectarse, emitir a todas las salas en las que estaba
socket.rooms.forEach(room => {
if (room !== socket.id) {
io.to(room).emit('system message', `Usuario ${socket.id} se ha desconectado de ${room}.`);
}
});
});
socket.emit('welcome', `Bienvenido al servidor Socket.IO con salas!`);
});
const PORT = 3001; // Puerto diferente para no colisionar
server.listen(PORT, () => {
console.log(`Servidor Socket.IO con salas escuchando en http://localhost:${PORT}`);
});
Ejemplo de Cliente con Rooms (React Native Socket.IO):
Podrías añadir un TextInput para ingresar el nombre de la sala y un botón para unirse a ella, y luego enviar mensajes específicos a esa sala.
// En App.js (parte relevante para rooms)
// ... imports y useState ...
const [currentRoom, setCurrentRoom] = useState('general');
const [roomInput, setRoomInput] = useState('');
useEffect(() => {
// ... configuración de socket ...
if (newSocket) {
newSocket.on('joinedRoom', (roomName) => {
setCurrentRoom(roomName);
setMessages(prev => [...prev, { id: Date.now(), text: `Has entrado en la sala: ${roomName}`, type: 'system' }]);
});
newSocket.on('roomMessage', (data) => {
if (data.room === currentRoom) {
const sender = data.id === socket.id ? 'Yo' : `Usuario ${data.id.substring(0, 4)}`;
setMessages(prev => [...prev, { id: Date.now(), text: `${sender} (${data.room}): ${data.message}`, type: data.id === socket.id ? 'client' : 'other' }]);
}
});
}
// ... resto del useEffect ...
}, [socket]); // Asegúrate de que este useEffect depende de `socket` para re-ejecutarse si el socket cambia
const joinRoom = () => {
if (socket && roomInput.trim()) {
socket.emit('joinRoom', roomInput.trim());
setRoomInput('');
}
};
const sendRoomMessage = () => {
if (socket && message.trim() && currentRoom) {
socket.emit('roomMessage', { room: currentRoom, message: message.trim() });
setMessage('');
}
};
// ... en el return de tu componente ...
<View style={styles.roomInputContainer}>
<TextInput
style={styles.input}
value={roomInput}
onChangeText={setRoomInput}
placeholder="Nombre de la sala..."
placeholderTextColor="#999"
/>
<Button title="Unirse a Sala" onPress={joinRoom} disabled={!socket || !socket.connected || !roomInput.trim()} />
</View>
<Text style={styles.currentRoomText}>Sala actual: <mark>{currentRoom}</mark></Text>
// ... cambiar el botón de enviar mensaje a sendRoomMessage ...
<Button title="Enviar" onPress={sendRoomMessage} disabled={!socket || !socket.connected || !message.trim()} />
// Añadir estilos para roomInputContainer y currentRoomText
// ...
🏁 Conclusión
Hemos explorado la implementación de comunicación en tiempo real en React Native utilizando tanto la API nativa de WebSockets como la potente librería Socket.IO. Mientras que ws te da un control más granular y es más ligero, Socket.IO simplifica gran parte de la complejidad, ofreciendo características esenciales para aplicaciones robustas como la reconexión automática, namespaces y rooms.
La elección entre uno y otro dependerá de los requisitos específicos de tu proyecto, pero en la mayoría de los casos de aplicaciones en tiempo real, Socket.IO será la opción más conveniente por su estabilidad y funcionalidades añadidas. ¡Ahora estás listo para construir aplicaciones React Native interactivas y dinámicas!
Tutoriales relacionados
- Optimización del Rendimiento en React Native: Desentrañando la Renderización y Boosters Claveintermediate20 min
- Navegación Avanzada en React Native: React Navigation v6intermediate20 min
- React Native con TypeScript: Desarrollo de Aplicaciones Robustas y Escalablesintermediate25 min
- React Native y GraphQL: Construyendo Aplicaciones Escalables con Apollo Clientintermediate25 min
- Integrando Realidad Aumentada en React Native con ViroReact: Guía Completaintermediate20 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!