Crear un componente de chat en tiempo real
Muestre mensajes en directo en una lista de chat desplazable mediante eventos WebSocket y el estado de React.
Crear un componente de chat en tiempo real es una lección gratuita de React Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de React Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de React Academy incluye 4 lecciones en total.
Arquitectura del componente de chat
Un chat en tiempo real tiene tres partes: una lista de mensajes (visualización), un campo de entrada de mensajes (envío) y la capa de conexión WebSocket/Socket.IO. Mantenga la lógica del socket en un hook personalizado.
Estructura de datos de los mensajes
Defina una interfaz de TypeScript para los mensajes del chat a fin de mantener la seguridad de tipos del componente en todo momento.
interface Message {
id: string;
text: string;
sender: string;
timestamp: number;
}
const [messages, setMessages] = useState<Message[]>([]);Hook useChat
Encapsule la conexión, el estado de los mensajes y la función de envío en un único hook.
function useChat(roomId: string) {
const [messages, setMessages] = useState<Message[]>([]);
useEffect(() => {
socket.connect();
socket.emit('join-room', roomId);
socket.on('message', (msg: Message) => setMessages(m => [...m, msg]));
return () => {
socket.off('message');
socket.emit('leave-room', roomId);
socket.disconnect();
};
}, [roomId]);
const sendMessage = useCallback((text: string) => {
const msg: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
socket.emit('message', msg);
}, []);
return { messages, sendMessage };
}Componente de lista de mensajes
Renderice los mensajes en una lista desplazable. Use useRef en el elemento centinela situado al final y desplácese hasta él cuando lleguen nuevos mensajes.
function MessageList({ messages }: { messages: Message[] }) {
const bottomRef = useRef<HTMLDivElement>(null);
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
return (
<div className="message-list">
{messages.map(msg => (
<div key={msg.id} className={`msg ${msg.sender === 'me' ? 'mine' : 'theirs'}`}>
<span>{msg.sender}</span>
<p>{msg.text}</p>
</div>
))}
<div ref={bottomRef} />
</div>
);
}Componente de entrada de mensajes
Un campo controlado que envía el mensaje al pulsar Enter o hacer clic en un botón. Vacíe el campo después de enviarlo.
function MessageInput({ onSend }: { onSend: (text: string) => void }) {
const [text, setText] = useState('');
const handleSend = () => {
if (!text.trim()) return;
onSend(text.trim());
setText('');
};
return (
<div className="input-row">
<input
value={text}
onChange={e => setText(e.target.value)}
onKeyDown={e => e.key === 'Enter' && handleSend()}
placeholder="Type a message..."
/>
<button onClick={handleSend}>Send</button>
</div>
);
}Montaje de la interfaz del chat
Combine el hook y los subcomponentes en un componente ChatRoom.
function ChatRoom({ roomId }: { roomId: string }) {
const { messages, sendMessage } = useChat(roomId);
return (
<div className="chat-room">
<h2>Room: {roomId}</h2>
<MessageList messages={messages} />
<MessageInput onSend={sendMessage} />
</div>
);
}Actualizaciones optimistas
Añada el mensaje al estado local inmediatamente, antes de que el servidor lo confirme, para ofrecer una respuesta instantánea. Sincronice el estado o elimine el mensaje si el servidor devuelve un error.
const sendMessage = useCallback((text: string) => {
const optimistic: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
setMessages(m => [...m, optimistic]); // instant feedback
socket.emit('message', optimistic, (err) => {
if (err) setMessages(m => m.filter(msg => msg.id !== optimistic.id));
});
}, []);Indicadores de escritura
Emita un evento typing al cambiar el contenido del campo (con debounce) y escuche los eventos de escritura de los demás usuarios para mostrar un indicador.
const emitTyping = useMemo(() => debounce(() => socket.emit('typing'), 300), []);
useEffect(() => {
socket.on('user-typing', (user) => setTypingUser(user));
return () => socket.off('user-typing');
}, []);Marcas de tiempo de los mensajes
Formatee las marcas de tiempo con Intl.DateTimeFormat para mostrarlas según el idioma y la región.
function formatTime(ts: number) {
return new Intl.DateTimeFormat('en', { hour: '2-digit', minute: '2-digit' }).format(ts);
}
<span className="timestamp">{formatTime(msg.timestamp)}</span>Confirmaciones de lectura
Emita un evento read cuando el usuario vea los mensajes y escuche las confirmaciones de lectura del servidor para mostrar marcas de verificación.
Lista de mensajes virtualizada
Para historiales de chat largos, use react-window o react-virtual para virtualizar la lista de mensajes y renderizar únicamente las filas visibles.
Limitación del historial de mensajes
Limite el array de mensajes del estado para evitar un crecimiento de memoria sin límites en sesiones largas.
socket.on('message', (msg: Message) => {
setMessages(prev => [...prev.slice(-499), msg]); // keep last 500
});Comprobación rápida
¿Cuál es el objetivo de desplazarse hasta el elemento div centinela inferior cuando llegan nuevos mensajes a una lista de chat?
Recapitulación
Construya un chat en tiempo real con un hook useChat que encapsule la lógica del socket, un MessageList con desplazamiento automático y un MessageInput que se vacíe al enviar. Use actualizaciones optimistas para ofrecer una respuesta instantánea y limite el historial de mensajes para evitar fugas de memoria.
Preguntas frecuentes
¿La lección «Crear un componente de chat en tiempo real» es gratis?
Sí — el texto completo de «Crear un componente de chat en tiempo real» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de React Academy, actualiza a CoddyKit PRO. El curso de React Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Crear un componente de chat en tiempo real»?
Muestre mensajes en directo en una lista de chat desplazable mediante eventos WebSocket y el estado de React. Practicas React Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar React Academy?
No se requiere experiencia previa. React Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Crear un componente de chat en tiempo real»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de React Academy?
Sí. Cada lección de React Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Fundamentos de WebSocket en el navegador
- Utilizar Socket.IO con React
- Crear un componente de chat en tiempo real
- Reconexión, gestión de errores y limpieza