DEV Community

Silviu Technology
Silviu Technology

Posted on

React: rendimiento que también se puede usar

Cuando se habla de rendimiento frontend, casi siempre aparecen los mismos números: tiempo de carga, tamaño del bundle y Core Web Vitals. Son útiles, pero no cuentan toda la historia. Una pantalla puede pintar rápido y seguir siendo dificil de usar si el botón no anuncia que está ocupado, si el foco salta al validar o si una animación tapa el mensaje de error.

En proyectos de React he encontrado que una mejora de rendimiento sostenible tiene dos resultados: la interfaz responde antes y la persona entiende mejor qué está pasando. Ese segundo resultado suele perderse en los dashboards. Incluso cuando alguien busca un temp mail for facebook para probar un flujo, el formulario sigue necesitando estados claros, teclado y mensajes comprensibles.

El rendimiento no termina en los milisegundos

Un formulario de registro puede tener una respuesta rápida y aun así sentirse lento. Por ejemplo, el usuario pulsa “Continuar”, no cambia nada visual, y vuelve a pulsar. La API recibe dos solicitudes y la interfaz parece rota. La solución no es solo bajar unos milisegundos: es hacer visible el estado de la acción.

Antes de optimizar, separo tres medidas:

  • Rendimiento técnico: cuánto tarda en pintar y responder.
  • Rendimiento percibido: cuánto tarda la persona en saber si su acción funcionó.
  • Rendimiento inclusivo: si esa información llega también con teclado, lector de pantalla o movimiento reducido.

Esta separación cambia las prioridades. Un spinner bonito no corrige un botón sin nombre accesible; un memo innecesario tampoco arregla una validación que borra el mensaje anterior.

Un patrón de React para estados que explican lo que pasa

Un componente pequeño puede modelar el flujo con estados explícitos. No hace falta introducir una librería para cada formulario:

function SubmitButton({status}) {
  const busy = status === "loading";

  return (
    <button type="submit" disabled={busy} aria-busy={busy}>
      {busy ? "Guardando…" : "Guardar cambios"}
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

El atributo disabled evita dobles envíos, mientras que aria-busy comunica el estado a tecnologías de asistencia. Después del envío, el resultado debería vivir en una región estable:

<p role="status" aria-live="polite">
  {status === "success" && "Cambios guardados."}
  {status === "error" && "No se pudo guardar. Revisa los campos e inténtalo otra vez."}
</p>
Enter fullscreen mode Exit fullscreen mode

El detalle importante es que el nodo no aparece y desaparece sin necesidad. Si su posición cambia en cada render, el lector de pantalla y el usuario de teclado tienen más trabajo. También conviene mantener la respuesta del servidor cerca del campo correspondiente, no solo en un toast que desaparece.

Para probar flujos que dependen de correo, ayuda separar la interfaz de la infraestructura. Las pruebas de signup sin inbox real muestran una dirección útil para aislar el backend. Y una cola visible para correos async recuerda que también debemos poder explicar cuándo llegó una señal externa.

CSS y accesibilidad: menos movimiento, más control

Los cambios de layout son una fuente silenciosa de frustración. Reservar espacio para mensajes de error y usar un contenedor con altura razonable reduce saltos visuales. Para las animaciones, la preferencia del sistema merece una regla sencilla:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms;
    animation-iteration-count: 1;
    transition-duration: 0.01ms;
    scroll-behavior: auto;
  }
}
Enter fullscreen mode Exit fullscreen mode

No conviene quitar todos los cambios de estado. Una frontera, un texto o un cambio de color con suficiente contraste puede comunicar progreso sin marear. Reviso el foco con Tab, aumento el zoom al 200% y compruebo que el mensaje no dependa solamente del color. A veces el contraste queda un poco raro en el primer intento, asi que lo mido y no me fio solo del ojo.

Cómo medir si el cambio ayudó

Mido la interacción completa, no solo el render. Algunas señales prácticas son el tiempo hasta que el botón comunica el resultado, la cantidad de envíos duplicados y el número de usuarios que corrigen el mismo campo más de una vez. Para una vista concreta, una métrica simple puede ser:

tiempo_de_confirmacion = resultado_visible - click_inicial
Enter fullscreen mode Exit fullscreen mode

Luego comparo antes y después con el mismo escenario de red y dispositivo. No inventaría una mejora a partir de una sola sesión. Un pequeño log con estado, duración y motivo de error suele ser más útil que diez capturas de pantalla.

Checklist para revisar un formulario

  • ¿El botón cambia de estado inmediatamente?
  • ¿Se bloquean los envíos duplicados sin bloquear la navegación?
  • ¿El foco llega al primer error real?
  • ¿Cada error tiene texto, no solo color o icono?
  • ¿La respuesta vive en una región anunciable?
  • ¿La interfaz funciona con movimiento reducido y zoom alto?
  • ¿Puedes relacionar una queja con un estado y una duración concretos?

La accesibilidad no es una capa que se añade después de optimizar. Es parte de la respuesta del producto. Cuando React, CSS y los eventos externos comparten estados claros, la interfaz se siente más rápida porque requiere menos adivinanzas. Ese es un tipo de rendimiento que los usuarios notan, aunque no siempre aparezca en Lighthouse.

Top comments (0)