Optimistic UI
Optimistic UI
8 reglasAplica el cambio al instante en acciones de alto exito
El patrón optimista funciona porque las acciones simples (dar like, marcar como leido, archivar, togglear) tienen tasas de exito del 97-99%. Reserva el patrón para esas acciones: muta el estado local de inmediato y dispara la petición en paralelo. Si revertir el cambio causaria confusión o perdida de datos, no uses Optimistic UI.
Smashing Magazine, True Lies Of Optimistic User InterfacesRefleja el cambio en menos de 100 ms
La percepción de instantaneidad tiene un límite neurologico de 100 ms: por encima de ese umbral el cerebro deja de atribuir el resultado a su propia acción. El modelo RAIL de Google fija el presupuesto de procesamiento de input en 50 ms para llegar a 100 ms extremo a extremo. Actualiza el estado local de forma sincrona en el mismo handler del evento, sin esperar el await del fetch.
web.dev, RAIL Model (input budget 50 ms)Haz rollback visible y notifica ante fallo
El contrato de honestidad exige que toda divergencia entre el estado local y el del servidor se resuelva sin perdida silenciosa de datos. Cuando la mutación falla, revierte el estado al snapshot previo y muestra una notificación clara que ofrezca reintentar. El rollback silencioso es el peor escenario: el usuario cree que su acción tuvo efecto cuando no lo tuvo.
TanStack Query onError + context, SWR rollbackOnErrorSenala el estado pendiente sin bloquear la interacción
El patrón optimista no elimina la necesidad de comunicar que una operación esta en curso, pero el indicador no debe anular la mejora de percepción. Usa opacidad reducida en el elemento afectado, un icono de sincronización de 16-20 px o un cambio sutil de borde, nunca un spinner modal que bloquee la pantalla. El indicador se retira en cuanto llega la confirmación; si es positiva, la transición es invisible.
CRITERIO · basado en RAIL: feedback para acciones >50 msReconcilia con el servidor usando idempotency y versión
El patrón optimista expone un riesgo: si el usuario repite la acción rápido, o si dos mutaciones concurrentes llegan en orden distinto al enviado, el estado final puede ser incorrecto. La solución tiene dos capas: el servidor acepta un Idempotency-Key por request para ignorar duplicados, y el cliente mantiene una cola con versión para detectar conflictos y rebasar sobre la respuesta autoritativa cuando llega un 409.
CockroachLabs, idempotency keys · React 19 conflict-safe mutationsNo uses el patrón en acciones criticas o irreversibles
El patrón optimista es una apuesta probabilistica: solo es honesto mientras la predicción de exito acierte casi siempre. Cuando la tasa de error supera el 3%, APIs inestables, validaciones complejas, pagos, eliminaciones permanentes, cada reversión es una fuente de confusión y desconfianza. En esos casos usa un skeleton o spinner honesto que comunique la incertidumbre real y espere la confirmación del servidor.
Smashing Magazine: error <1-3%, exito 97-99%Anuncia el resultado real con una region aria-live
Los usuarios de lector de pantalla no perciben el cambio visual optimista: solo escuchan lo que se les anuncia. Crea una region role="status" vacia desde el primer render y actualiza su contenido con el resultado real del servidor; si hubo rollback, anuncia el error de inmediato. Sin esto, el usuario asistivo cree que nada ocurrio o toma el estado optimista como definitivo.
Reserva espacio para evitar CLS al reconciliar
El mayor riesgo de flicker es cuando el estado optimista difiere del real del servidor: si la respuesta trae dimensiones distintas, los elementos existentes se desplazan y generan Layout Shift. Inserta el contenido optimista con la misma estructura y altura que esperas del servidor para reconciliar in-place. CLS es un Core Web Vital: un score ≤0.1 es la meta para experiencia buena.
web.dev, Cumulative Layout Shift (meta CLS ≤0.1)- R-338 Aplica el cambio al instante en acciones de alto exito
- R-339 Refleja el cambio en menos de 100 ms
- R-340 Haz rollback visible y notifica ante fallo
- R-341 Senala el estado pendiente sin bloquear la interacción
- R-342 Reconcilia con el servidor usando idempotency y versión
- R-343 No uses el patrón en acciones criticas o irreversibles
- R-344 Anuncia el resultado real con una region aria-live
- R-345 Reserva espacio para evitar CLS al reconciliar