DEV Community

Silviu Technology
Silviu Technology

Posted on

React: accesibilidad sin pagar con rendimiento

En muchos equipos frontend, accesibilidad y rendimiento se revisan en momentos distintos. Eso crea una falsa elección: primero hacemos que el formulario sea rápido y despues añadimos mensajes para lectores de pantalla. En la práctica, una interfaz bien anunciada suele ser también más clara y más barata de renderizar.

Este patrón sirve para formularios que validan un email de forma asíncrona, por ejemplo durante un registro. La idea es separar tres cosas: el valor que escribe la persona, el estado de la petición y el mensaje que debe escuchar.

El problema: accesibilidad y rendimiento parecen competir

Un error común es mostrar un spinner global mientras llega la respuesta. El foco salta, el botón cambia de tamaño y la persona no sabe si su acción se guardó. Otro es ejecutar una petición en cada tecla: funciona en una demo, pero produce trabajo innecesario y respuestas fuera de orden.

Para una dirección de correo temporal usada en pruebas, un entorno aislado como un buzón de pruebas con pistas útiles puede ayudar a observar el flujo sin llenar una bandeja real. Para producción, las reglas de privacidad y verificación deben ser explícitas.

Una pequeña máquina de estados

En vez de varios booleanos (isLoading, hasError, isValid), uso un estado pequeño y visible: idle, checking, valid o invalid. Así el componente tiene una sola fuente de verdad y resulta más facil probarlo.

const [status, setStatus] = useState("idle");
const [message, setMessage] = useState("");

async function checkEmail(value) {
  setStatus("checking");
  setMessage("Comprobando la dirección…");
  const result = await verifyEmail(value);
  setStatus(result.ok ? "valid" : "invalid");
  setMessage(result.ok ? "La dirección parece válida." : "Revisa la dirección e inténtalo otra vez.");
}
Enter fullscreen mode Exit fullscreen mode

El mensaje debe estar conectado con aria-live="polite", no con un alert agresivo que interrumpa cada interacción. El botón puede quedar deshabilitado mientras se comprueba, pero el texto de estado sigue siendo necesario para quien navega con teclado.

CSS que ayuda a ambos objetivos

Reserva espacio para el mensaje antes de que aparezca. Esto evita un salto de layout y hace más estable la lectura visual. También define un foco visible que no dependa solo del color.

.field-message { min-height: 1.5rem; }
.email-input:focus-visible {
  outline: 3px solid #2457d6;
  outline-offset: 2px;
}
Enter fullscreen mode Exit fullscreen mode

No ocultes el texto con display: none mientras está vacío si el contenedor va a cambiar de tamaño. Un espacio reservado pequeño es una decisión de UX, no un desperdicio de píxeles. En móviles, comprueba además que el foco no quede detrás del teclado.

Pruebas concretas antes de publicar

Primero prueba el teclado: tabula hasta el campo, escribe, espera el resultado y confirma que el foco se mantiene. Después activa un lector de pantalla y verifica que el cambio se anuncia una sola vez. Si la petición tarda, el mensaje no debería repetirse por cada render.

En rendimiento, cancela o ignora respuestas antiguas. Un AbortController evita que una comprobación vieja reemplace el resultado nuevo. También conviene aplicar debounce solo cuando la validación remota realmente lo necesita; no conviertas cada campo en una pequeña cola de red.

Si tu flujo usa un burner email address durante una prueba manual, documenta que es un dato de test y elimina la cuenta cuando termine. Una opción de contexto para generar datos efímeros es medir cada paso de un flujo de email, especialmente si necesitas saber donde se pierde la experiencia.

Checklist final

  • El foco permanece en el campo después de una respuesta.
  • El estado se anuncia mediante un único aria-live.
  • El mensaje tiene espacio reservado y no mueve el formulario.
  • Las respuestas fuera de orden no pisan el valor más reciente.
  • El contraste del foco y de los errores se puede ver sin depender del color.
  • Las pruebas no usan una dirección real: puedes usar tempmailso para un escenario controlado y, en otro caso, una cuenta de tempmailso de prueba según las reglas de tu equipo.

La accesibilidad no tiene por qué ser una capa lenta al final. Cuando el estado, el foco y el layout se diseñan juntos, React renderiza una interfaz más predecible para todo el mundo, y mantenerla cuesta menos.

Top comments (0)