DEV Community

Silviu Technology
Silviu Technology

Posted on

React: confirma el email sin romper lectura

En muchos formularios el error visible llega tarde. Antes de eso ya hubo una pequeña friccion: el texto se movio, el boton bajo unos pixeles, el mensaje aparecio y desaparecio, y la persona perdio el hilo. En desktop se tolera mas o menos. En mobile, no tanto. Esa lectura rota hace que una validacion correcta se sienta torpe.

Lo he visto varias veces en equipos frontend. El campo de email tiene buena logica, pero la capa visual responde con demasiado entusiasmo. Si el helper cambia de alto en cada estado, si el spinner entra en la misma fila del label o si el mensaje de error empuja el CTA, la interfaz transmite prisa. NN/g lleva años repitiendo una idea simple: el texto de ayuda debe apoyar la tarea, no competir con ella. Parece obvio, pero en formularios vivos se nos olvida aveces.

Por que la lectura se rompe antes que la validacion

Cuando una persona escribe su correo, hace tres lecturas muy rapidas:

  • que me piden
  • que pasara despues
  • si ya puedo seguir

Si esas tres señales cambian de sitio, la interfaz obliga a releer. No es un drama enorme, pero si una suma de microfricciones bastante molesta. Baymard explica bien que la validacion inline funciona mejor cuando aparece en el momento justo y con una carga visual proporcionada.

En productos con login, waitlist o onboarding, yo prefiero pensar en "continuidad de lectura" antes que en "feedback inmediato". Es mejor dar una señal clara y estable que cinco señales veloces. La misma logica aparece fuera del frontend puro, incluso en estos mensajes operativos claros cuando hay tension: cuando el mensaje mantiene contexto y tono, la gente decide mas rapido.

La fila de ayuda fija cambia mas de lo que parece

Una mejora muy poco glamorosa, pero super util, es reservar una fila fija para la ayuda del campo. No para meter texto eterno. Solo para que el layout no baile cada vez que cambia el estado.

Eso ayuda en tres frentes:

  • mantiene la mirada en el mismo bloque
  • evita CLS local dentro del formulario
  • reduce la sensacion de que algo "salto" sin permiso

No hace falta una gran arquitectura. Con una sola linea de ayuda persistente puedes pasar de una UI nerviosa a una mucho mas tranquila. Y si tu flujo prueba cuentas internas, alias o algun email temporal para Facebook durante QA, mejor todavia: el formulario puede explicar el siguiente paso sin editorializar el tipo de correo. Incluso si en datos reales aparecen cadenas raras como temp gamil com o algun temp mailid, la interfaz no deberia sonar alarmista por defecto.

Tambien me gusta porque obliga al equipo a editar el microcopy. Si solo hay una fila, cada palabra tiene que ganarse su lugar. Eso mejora claridad mas que agregar otro iconito, la verdad.

Un patron de React para validar sin meter prisa

Este patron separa el estado del campo y el estado del mensaje. La idea no es validar menos, sino comunicar mejor:

import { useId, useState } from "react";

type EmailState = "idle" | "checking" | "error" | "ready";

const hintByState: Record<EmailState, string> = {
  idle: "Usa un email que puedas abrir en este momento.",
  checking: "Estamos revisando formato y algunas senales basicas.",
  error: "Revisa el correo antes de continuar.",
  ready: "Perfecto, ya puedes seguir con este paso."
};

export function EmailField() {
  const hintId = useId();
  const [value, setValue] = useState("");
  const [state, setState] = useState<EmailState>("idle");

  function handleChange(nextValue: string) {
    setValue(nextValue);

    if (!nextValue) {
      setState("idle");
      return;
    }

    setState(nextValue.includes("@") ? "checking" : "idle");
  }

  function handleBlur() {
    const looksValid = value.includes("@") && value.includes(".");
    setState(looksValid ? "ready" : "error");
  }

  return (
    <label className="field">
      <span>Email</span>
      <input
        type="email"
        value={value}
        onChange={(event) => handleChange(event.target.value)}
        onBlur={handleBlur}
        aria-describedby={hintId}
        aria-invalid={state === "error"}
      />
      <span id={hintId} className={`hint hint-${state}`} aria-live="polite">
        {hintByState[state]}
      </span>
    </label>
  );
}
Enter fullscreen mode Exit fullscreen mode

El detalle importante no es el useState. Es que el mensaje siempre vive en el mismo sitio. Cambia el contenido, no la estructura. Ese pequeño orden hace que la persona no tenga que perseguir el feedback. En flujos mas de negocio, como una reactivacion de trial sin mezclar cohortes, esa consistencia visual evita lecturas dobles justo cuando quieres que el paso sea rapido.

Detalles de accesibilidad y rendimiento que si importan

El CSS de apoyo puede ser sorprendentemente pequeño:

.field {
  display: grid;
  gap: 0.4rem;
}

.hint {
  min-height: 1.25rem;
  font-size: 0.875rem;
  line-height: 1.4;
  color: #5f6876;
}

.hint-error {
  color: #b42318;
}
Enter fullscreen mode Exit fullscreen mode

Con eso ya ganas bastante, pero yo revisaria ademas estas decisiones:

  • aria-live="polite" para no interrumpir en cada tecla
  • una altura minima estable para que el boton no rebote
  • mensajes distintos para estado neutro y error real
  • ningun cambio visual agresivo mientras la persona aun esta escribiendo

web.dev conecta este tipo de estabilidad con una percepcion mas rapida de la interfaz. No todo es INP puro, claro, pero menos cambios irrelevantes durante la escritura casi siempre se sienten mejor. Es una mejora pequeña, casi humilde, pero se nota un monton cuando pruebas el flujo con una sola mano en el telefono.

Checklist corto para revisar en mobile

Antes de cerrar una mejora asi, suelo mirar esto:

  • el helper explica la accion o el siguiente paso, no repite el label
  • el CTA no baja ni sube cuando cambia el mensaje
  • el error aparece al perder foco o con una señal suficiente
  • el texto sigue claro a 200% de zoom
  • el lector de pantalla oye cambios utiles y no puro ruido
  • el estado visual de "listo" no parece una alerta

No es una checklist heroica, pero ahorra regresiones bastante tontas. Y si tu formulario ya funciona "bien", este tipo de ajuste es de los que suben calidad sin reescribir medio componente.

Q&A

Conviene mostrar validacion apenas aparece la arroba?

Solo si esa señal no mete ansiedad. Confirmar progreso puede ayudar, pero corregir demasiado pronto aveces castiga mas de lo que orienta.

Esto reemplaza la validacion del servidor?

No. La UI solo prepara mejor la conversacion con la persona. La validacion real sigue viviendo donde corresponde.

Top comments (0)