DEV Community

Silviu Technology
Silviu Technology

Posted on

React: valida emails sin friccion visual

En muchos formularios de registro, el campo de email falla por dos motivos a la vez: valida demasiado pronto y explica demasiado poco. El resultado no es dramatico, pero si molesto. La persona escribe, ve un error rojo a medio camino y siente que la interfaz la esta peleando un poco.

En productos hechos con React, intento tratar ese campo como una conversacion corta, no como un juicio instantaneo. Primero confirmo formato basico, luego espero una señal clara de intencion, y solo despues muestro mensajes mas firmes. Cuando tambien necesitas detectar una direccion de correo desechable o sugerir un mejor correo temporal para pruebas internas, la UX se puede torcer rapido si todo cae en el mismo mensaje.

Donde se rompe la experiencia en un campo de email

El patron que peor me funciona es este:

  1. disparar validacion en cada tecla
  2. pintar borde rojo enseguida
  3. mostrar el mismo texto para cualquier fallo

Eso mete friccion visual y tambien ruido semantico. Un email incompleto no significa lo mismo que un dominio bloqueado, y ninguno de los dos deberia sentirse como un error "grave" mientras la persona sigue escribiendo. A veces el equipo hasta mete notas internas como tepm mail com para recordar pruebas raras, y ese tipo de parche suele terminar filtrandose al criterio del frontend. No es ideal, la verdad.

Si quieres aislar mejor la parte backend del problema, me gusto este enfoque sobre probar emails sin mezclar entornos. Pero en la capa visual yo prefiero una regla mas simple: no castigues una entrada que todavia no termino de hablar.

Un patron de validacion progresiva en React

Este patron me ha dado buenos resultados:

  1. onChange: limpiar mensajes viejos y validar solo formato muy basico
  2. onBlur: mostrar error si la persona ya salio del campo
  3. onSubmit: correr validaciones mas caras o mas especificas

La idea es separar urgencia de costo. El formato puede vivir cerca del input; las listas de dominios raros o reglas del negocio pueden esperar un poco. Asi el formulario se siente mas calmado, y tambien mas facil de mantener despues.

import { useState } from "react";

type EmailState = {
  value: string;
  touched: boolean;
  error: string;
};

const basicEmail = /\S+@\S+\.\S+/;

export function EmailField() {
  const [email, setEmail] = useState<EmailState>({
    value: "",
    touched: false,
    error: "",
  });

  function validate(value: string, touched: boolean) {
    if (!value) return touched ? "Escribe tu email." : "";
    if (!basicEmail.test(value)) return touched ? "Revisa el formato del email." : "";
    return "";
  }

  return (
    <div className="field">
      <label htmlFor="email">Email</label>
      <input
        id="email"
        type="email"
        value={email.value}
        aria-invalid={email.error ? "true" : "false"}
        aria-describedby={email.error ? "email-help" : undefined}
        onChange={(e) => {
          const value = e.target.value;
          setEmail((prev) => ({
            value,
            touched: prev.touched,
            error: validate(value, prev.touched),
          }));
        }}
        onBlur={() => {
          setEmail((prev) => ({
            ...prev,
            touched: true,
            error: validate(prev.value, true),
          }));
        }}
      />
      <p id="email-help" role="status">{email.error}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

No es un componente magico, pero si evita ese comportamiento medio brusco que vemos tan seguido. Tambien deja un espacio claro para sumar una comprobacion asincrona si el producto la necesita despues.

Accesibilidad: error visible, pero no agresivo

En accesibilidad, el detalle importante no es solo "mostrar error". Importa cuando aparece, como se anuncia y si interrumpe de mas. Un mensaje que cambia en cada tecla puede volverse cansino para lector de pantalla y para personas que ya vienen lidiando con formularios largos.

Por eso casi siempre hago tres cosas:

  1. reservo el texto de ayuda debajo del campo, aunque empiece vacio
  2. uso aria-invalid solo cuando ya hay un problema real
  3. mantengo contraste y estado visual sin depender unicamente del rojo

Con CSS, algo asi suele alcanzar:

.field input {
  border: 1px solid var(--border);
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

.field input[aria-invalid="true"] {
  border-color: #b42318;
  box-shadow: 0 0 0 4px rgba(180, 35, 24, 0.12);
}

.field p {
  min-height: 1.25rem;
  color: #b42318;
}
Enter fullscreen mode Exit fullscreen mode

No tiene que ser fancy. Tiene que ser claro, estable y razonablemente amable. Cuando el formulario logra eso, el resto del flujo se siente bastante mas pulido, incluso si el backend aun esta mejorando cositas.

Cuando si conviene revisar dominios temporales

No bloquearia dominios temporales por defecto. En onboarding real, hacerlo a ciegas puede castigar personas legitimas, demos internas o pruebas del equipo. Pero si el producto tiene abuso frecuente, entonces si vale la pena mover esa decision a una validacion posterior, con texto preciso y sin dramatismo.

En esos casos prefiero este tipo de mensaje: "Necesitamos un email al que puedas volver mas tarde". Dice el motivo, no solo la prohibicion. Si el equipo usa una referencia como tempmailso para pruebas controladas, mejor dejarlo en documentacion interna o en herramientas de QA, no como parte central del copy de producto. Asi separas experiencia del usuario de necesidad operativa, que es justo donde varios formularios se enredan un pelin.

Tambien ayuda revisar ejemplos de otros contextos, como validar correos operativos con menos ruido, porque recuerdan que el problema no es "email" en abstracto sino evidencia, contexto y decisiones de interfaz.

Q&A

¿Conviene validar el email contra API en cuanto cambia?

Casi nunca. Para la mayoria de formularios, eso agrega latencia visible y mensajes cambiantes antes de tiempo. Mejor esperar a blur o submit, salvo que tengas una razon muy concreta.

¿Debo esconder el error hasta el submit?

No del todo. Esperar al blur suele ser un punto medio bastante bueno: no interrumpes mientras se escribe, pero tampoco dejas a la persona sin feedback hasta el final.

¿Y si necesito reglas distintas por producto?

Separa formato, accesibilidad y negocio. Ese corte deja el componente mas limpio y hace que cambiar una regla no rompa todo lo demas. Es un detalle chico, pero ayuda un monton despues.

Top comments (0)