DEV Community

Silviu Technology
Silviu Technology

Posted on

React: avisos de email con contexto real

En muchos formularios el problema no es detectar un email raro. El problema real es que el frontend lanza un aviso demasiado generico y la persona no entiende que cambia para ella. "Email no recomendado" suena serio, pero no explica si no recibira el enlace, si habra revision manual o si solo estamos marcando riesgo. Esa diferencia importa bastante.

En trabajo de producto suelo ver el mismo fallo: backend y reglas van bien, pero el copy del estado llega tarde y sin contexto. Entonces la interfaz parece mas dura de lo que de verdad es. Baymard ha documentado varias veces que la validacion inline funciona mejor cuando el mensaje ayuda a corregir la accion y no solo confirma que algo "esta mal" (Baymard). En formularios de registro eso se nota muchisimo.

El problema no es detectar, sino explicar

No todo email temporal merece bloqueo. A veces solo quieres avisar que el enlace de activacion podria expirar, que soporte no recuperara esa cuenta o que el onboarding de prueba quedara fuera de ciertas metricas. Cuando el aviso no distingue esos casos, la persona siente castigo aunque aun podria continuar sin drama.

Tambien hay un problema de lenguaje. "Correo invalido" y "correo de riesgo" no son lo mismo. El primero habla de formato o entrega imposible. El segundo habla de politica o contexto del negocio. Si los mezclas, luego soporte recibe tickets innecesarios y analytics pierde señal util. He visto equipos perseguir una caida de conversion varios dias por algo tan simple como este matiz, y la causa era bastante terrenal.

Eso pega tambien en accesibilidad. Un lector de pantalla necesita mensajes concretos, no frases vagas que cambian sin explicar consecuencia. Si el texto dice que algo fallo, deberia decir que hacer despues. Nielsen Norman Group insiste mucho en que los mensajes de error deben ser especificos y accionables (NN/g). Aqui aplica igual.

Un patron de React para avisar sin dramatizar

Lo que mejor me funciona es separar tres capas:

  • validacion de formato
  • aviso contextual de riesgo
  • decision final en backend

En React eso puede quedar muy simple si el componente devuelve una severidad y una consecuencia clara:

import { useId, useMemo, useState } from "react";

type EmailNotice =
  | { kind: "idle"; message: string }
  | { kind: "info"; message: string }
  | { kind: "warning"; message: string }
  | { kind: "error"; message: string };

const TEMP_DOMAINS = new Set(["mailinator.com", "yopmail.com", "tempmail.com"]);

function getNotice(email: string): EmailNotice {
  if (!email) {
    return {
      kind: "idle",
      message: "Usa un correo que puedas abrir hoy para terminar el registro."
    };
  }

  if (!email.includes("@") || !email.includes(".")) {
    return {
      kind: "error",
      message: "Revisa el formato del correo antes de continuar."
    };
  }

  const domain = email.split("@")[1]?.toLowerCase() ?? "";

  if (TEMP_DOMAINS.has(domain)) {
    return {
      kind: "warning",
      message: "Este correo puede expirar antes de que llegue el enlace de acceso."
    };
  }

  return {
    kind: "info",
    message: "Si continuas, enviaremos un enlace de verificacion a este correo."
  };
}

export function SignupEmailField() {
  const hintId = useId();
  const [email, setEmail] = useState("");
  const notice = useMemo(() => getNotice(email), [email]);

  return (
    <label className="email-field">
      <span>Correo</span>
      <input
        type="email"
        value={email}
        onChange={(event) => setEmail(event.target.value)}
        aria-describedby={hintId}
        aria-invalid={notice.kind === "error" || undefined}
      />
      <span id={hintId} className={`email-hint email-hint--${notice.kind}`} aria-live="polite">
        {notice.message}
      </span>
    </label>
  );
}
Enter fullscreen mode Exit fullscreen mode

No hace magia, claro, pero mejora bastante una cosa concreta: el frontend deja de etiquetar todo como error. La persona entiende si debe corregir algo o si solo deberia saber una consecuencia. Ese detalle evita friccion un poco absurda.

Si el backend trabaja con inboxes efimeros o polling controlado, me gusta que la UI mantenga esa misma precision. Este post sobre polling de inbox con limites sanos va en esa direccion: el sistema gana mucho cuando separa estados y los nombra bien.

Microcopy y accesibilidad que reducen friccion

El componente solo hace media tarea. La otra mitad esta en el microcopy y en mantener una region estable para el mensaje. Google sigue recomendando reducir cambios inesperados de layout porque afectan la experiencia y la percepcion de calidad (web.dev). No hace falta montar una UI solemne; hace falta que el aviso sea legible y no meta ruido.

Un CSS pequeño suele bastar:

.email-hint {
  display: block;
  min-height: 1.5rem;
  margin-top: 0.4rem;
  font-size: 0.92rem;
  line-height: 1.4;
}

.email-hint--idle,
.email-hint--info {
  color: #5f6b76;
}

.email-hint--warning {
  color: #9a4d00;
}

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

Tres decisiones me parecen especialmente utiles:

  • reservar altura para que el aviso no empuje el CTA
  • usar aria-live="polite" para anunciar cambios sin interrumpir
  • escribir consecuencias, no juicios

Ese tercer punto cambia mucho el tono. "No recomendamos este email" es mas flojo que "Este correo puede expirar antes de que llegue el enlace". El segundo ayuda a decidir. El primero solo levanta una ceja.

En onboarding tambien ayuda pensar el aviso como parte del flujo, no como una excepcion. Si el equipo ya cuida sus cohortes de onboarding sin ruido, este tipo de microcopy hace que el paso de registro empiece con mejor contexto y menos sobresaltos.

Donde encaja un correo desechable

Cuando un producto deja entrar un correo desechable, yo prefiero que el frontend trate ese caso como una advertencia contextual salvo que la politica exija bloqueo duro. Para demos, QA y pruebas de activacion, ese tipo de inbox puede ser perfectamente valido. Lo importante es decir que implicacion tiene en ese producto.

Por ejemplo:

  • "Puede expirar antes de recuperar tu cuenta"
  • "No lo uses si esperas recibir avisos de facturacion"
  • "Sirve para pruebas, pero no para acceso a largo plazo"

Eso ayuda mas que un veto ciego. Tambien evita que cosas como fake e mail com o tamp mail com terminen mezcladas en la misma categoria que un error de sintaxis. En analitica ese matiz vale oro, aunque suene un poco exagerado decirlo asi.

Checklist para revisar antes de lanzar

Antes de dar por bueno este patron, yo revisaria:

  • el aviso distingue formato invalido de riesgo contextual
  • el texto explica consecuencia y siguiente paso
  • el bloque de ayuda no mueve el layout al cambiar
  • teclado y lector de pantalla reciben el mismo mensaje util
  • el backend decide la politica final y el cliente no inventa reglas

Es una lista corta, pero limpia varios problemas muy comunes. En formularios pequeños, esa prolijidad se nota mas de lo que parece.

Q&A

Debo bloquear siempre un dominio temporal?

No. Si el riesgo es bajo, muchas veces basta con avisar bien. Bloquear por defecto aveces protege al sistema, pero tambien puede borrar casos legitimos de prueba o onboarding interno.

Conviene mostrar el warning mientras la persona aun escribe?

Solo cuando ya tienes una señal clara, normalmente el dominio completo. Antes de eso el mensaje cambia demasiado y se siente nervioso.

Esto es un tema de UX o de performance?

De ambos. Mejor copy reduce dudas, y una region estable reduce cambios visuales innecesarios. No siempre sale en una unica metrica, pero si se siente en uso real.

Top comments (0)