Capítulo 2: React y el Hook useChat
En el capítulo anterior generamos texto con streaming en la terminal. Ahora llevaremos el streaming a React con useChat, el hook que hace que construir interfaces de chat sea casi trivial.
Por qué necesitas un hook especializado
Tu primer instinto podría ser: "Es solo un fetch con useState". Pero hay varios problemas con ese approach:
- No hay streaming: El usuario ve pantalla vacía hasta que termina la respuesta
- No hay historial estructurado: Mensajes como strings planos, sin roles ni metadata
- No hay manejo de errores mid-stream: ¿Qué pasa si la conexión falla a mitad?
- Re-renders excesivos: Cada token causa un re-render de todo el componente
useChat resuelve todo con una API declarativa:
Cambio en v6: El hook ya no maneja el input internamente. Usas
useStatepara el campo de texto,sendMessagepara enviar,statusen lugar deisLoading, y los mensajes tienenpartsen lugar decontent.
Anatomía de useChat
El hook devuelve un objeto con estas propiedades esenciales:
Los estados de status:
ready: Listo para recibir inputsubmitted: Mensaje enviado, esperando respuestastreaming: Recibiendo tokens del servidorerror: Hubo un error en la petición
El tipo Message en v6
Los mensajes usan parts en lugar de content:
Esta estructura permite mensajes más ricos que pueden contener texto, invocaciones de herramientas, y resultados — todo en el mismo mensaje.
El protocolo de streaming
useChat usa un protocolo de texto optimizado para streaming, no JSON plano. Cada línea tiene un prefijo:
| Prefijo | Significado |
|---|---|
0: | Chunk de texto |
2: | Tool call |
8: | Tool result |
d: | Metadata final (finish reason, usage) |
e: | Error |
JSON requiere el documento completo para parsearlo. Con este protocolo, cada línea es independiente y parseable inmediatamente.
Implementación paso a paso
1. El servidor (React Router v7)
Nota v6:
convertToModelMessagesreemplaza aconvertToCoreMessagesy ahora es async. TambiéntoDataStreamResponse()fue reemplazado portoUIMessageStreamResponse().
2. El cliente
3. Registrar la ruta
En v6, useChat() usa /api/chat por defecto.
Patrones de UI para Chat
Indicador de escritura
Scroll automático inteligente
El scroll debe respetar cuando el usuario está leyendo mensajes anteriores:
Optimización de Re-renders
useChat puede causar muchos re-renders — cada token actualiza el estado.
React.memo para mensajes
Separar mensaje en streaming
Customización
Callbacks
Transport personalizado
Cancelación
Edge Cases
Enviar mientras genera
Múltiples instancias
Persistir conversación
Error mid-stream
Resumen
| Concepto | Qué aprendiste |
|---|---|
useChat | Hook que maneja estado y streaming de chat |
sendMessage | Reemplaza a append — envía mensajes |
status | Estados: ready, submitted, streaming, error |
message.parts | Nuevo formato con array de partes tipadas |
transport | Configuración de endpoint y headers |
regenerate | Reemplaza a reload — reintenta última respuesta |
| Optimización | React.memo y split components |
Migración automática v5 → v6
En el próximo capítulo abriremos el capó del streaming. Usaremos Hono como microscopio para ver exactamente qué viaja por el wire—cada text-delta, cada finish-step. Cuando tu chat falle en producción, este conocimiento te salvará.
¿Ya compraste el libro?
Si compraste el libro y no encuentras tu email de descarga, ingresa tu email y te enviamos un nuevo enlace.
