React 19 de Cero a Experto / React 19 moderno
useOptimistic: UI que responde al instante
Cuando envías un mensaje de WhatsApp, aparece al instante con un relojito, aunque el servidor aún
no lo confirmó. Si algo falla, se marca en rojo. Eso es la UI OPTIMISTA: asumir que la acción va a
tener éxito y mostrarlo YA, corrigiendo solo si falla. Hace que la app se sienta instantánea. React
19 trae un hook dedicado, useOptimistic, que maneja ese estado temporal por ti. Hoy entiendes el
patrón y cómo React lo automatiza.
El mesero que anota tu pedido de una
El patrón manual (el que ya podrías hacer)
Antes de useOptimistic, harías la ilusión a mano: agregas el item con una marca de "pendiente",
y al confirmar lo reemplazas por el real (o lo quitas si falló). Corre en vivo:
Agrega un gasto: aparece al instante con opacidad y un relojito (⏳), y ~1.2s después se confirma
(✓) o desaparece si el servidor "falló" (1 de cada 4). Funciona, pero mezclas el estado optimista
con el real en el mismo array y manejas a mano la reversión. React 19 separa esas dos capas.
El "después": useOptimistic
useOptimistic toma tu estado REAL (confirmado) y te da una versión con los cambios optimistas
aplicados encima. Cuando la acción termina, React descarta la capa optimista y vuelve al estado
real —que para entonces ya incluye el dato confirmado (o no, si falló)—:
import { useOptimistic, useState } from "react";
function Lista({ gastos, agregarReal }: Props) {
// estado optimista: parte del real y aplica cambios provisionales
const [optimistas, agregarOptimista] = useOptimistic(
gastos,
(estado: Gasto[], nuevoNombre: string) => [
...estado,
{ id: Date.now(), nombre: nuevoNombre, pendiente: true }, // se ve YA
]
);
async function accion(formData: FormData) {
const nombre = String(formData.get("nombre"));
agregarOptimista(nombre); // 1. muestra el item provisional al instante
await agregarReal(nombre); // 2. envía al servidor de verdad
// 3. React descarta la capa optimista sola; queda el estado real actualizado
}
return (
<form action={accion}>
<input name="nombre" />
<ul>
{optimistas.map((g) => (
<li key={g.id} style={{ opacity: g.pendiente ? 0.5 : 1 }}>
{g.nombre} {g.pendiente ? "⏳" : "✓"}
</li>
))}
</ul>
</form>
);
}useOptimistic(estadoReal, fnActualizadora) devuelve [valorOptimista, aplicarOptimista]. Llamas
aplicarOptimista(dato) y la UI muestra el cambio provisional al instante; mientras tanto, tu
acción real corre. Cuando termina, React DESCARTA automáticamente la capa optimista y vuelve al
estado real —que ya tiene el dato confirmado, o no lo tiene si el envío falló—. No manejas la
reversión a mano: si la acción no actualizó el estado real, el item optimista simplemente desaparece
al descartarse la capa.
¿Qué hace useOptimistic y por qué no tienes que revertir manualmente si la acción falla?
Mini-reto
En tu proyecto React 19 (o razonando el flujo en papel): 1) parte de una lista de mensajes en
useState; 2) con useOptimistic, crea [mensajesOptimistas, agregarOptimista] cuya función
actualizadora añada el mensaje nuevo con enviando: true; 3) en la acción del form, llama primero
agregarOptimista(texto) (se ve YA) y luego await enviar(texto) que actualiza el estado real.
Piensa: ¿qué pasa en la UI si enviar lanza un error y NO actualizas el estado real?
Qué sigue
Ya haces UIs instantáneas. La siguiente novedad de React 19 es un hook con un nombre engañosamente
simple: use(). Rompe reglas que creías inquebrantables —puede leer una promesa directamente, y
puede llamarse dentro de un if—. La próxima lección explica qué hace y por qué es distinto a todos
los demás hooks.