EmailVerify LogoEmailVerify

React

Email checker for React. Real-time email verification in React forms and components.

Agregue verificación de correo en tiempo real a sus aplicaciones React. Valide correos mientras los usuarios escriben, prevenga envíos inválidos y mejore la UX de formularios.

Instalación

npm install @emailverify/react @emailverify/node
yarn add @emailverify/react @emailverify/node
pnpm add @emailverify/react @emailverify/node

Inicio Rápido

Input de Correo Básico con Validación

import { useState } from 'react';
import { useEmailVerification } from '@emailverify/react';

function SignupForm() {
  const [email, setEmail] = useState('');
  const { verify, result, isLoading, error } = useEmailVerification();

  const handleEmailBlur = async () => {
    if (email) {
      await verify(email);
    }
  };

  return (
    <form>
      <div className="form-group">
        <label htmlFor="email">Email</label>
        <input
          id="email"
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          onBlur={handleEmailBlur}
          className={result?.status === 'invalid' ? 'error' : ''}
        />

        {isLoading && <span className="loading">Verifying...</span>}

        {result?.status === 'invalid' && (
          <span className="error-message">
            Please enter a valid email address
          </span>
        )}

        {result?.status === 'valid' && (
          <span className="success-message">✓ Email verified</span>
        )}

        {result?.result?.disposable && (
          <span className="warning-message">
            Please use a permanent email address
          </span>
        )}
      </div>

      <button type="submit" disabled={result?.status !== 'valid'}>
        Sign Up
      </button>
    </form>
  );
}

Configuración del Provider

Envuelva su app con el provider de EmailVerify:

// App.jsx or main.jsx
import { EmailVerifyProvider } from '@emailverify/react';

function App() {
  return (
    <EmailVerifyProvider
      config={{
        // API calls go through your backend
        apiEndpoint: '/api/verify-email',
      }}
    >
      <YourApp />
    </EmailVerifyProvider>
  );
}

Nunca exponga su clave de API en código del lado del cliente. Siempre verifique correos a través de su backend.

Ruta API del Backend

Cree un endpoint API seguro para la verificación de correo:

// pages/api/verify-email.js (Next.js) or your Express route
import { EmailVerify } from '@emailverify/node';

const client = new EmailVerify({
  apiKey: process.env.EMAILVERIFY_API_KEY,
});

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const { email } = req.body;

  if (!email) {
    return res.status(400).json({ error: 'Email is required' });
  }

  try {
    const result = await client.verify(email);
    return res.json(result);
  } catch (error) {
    console.error('Verification error:', error);
    return res.status(500).json({ error: 'Verification failed' });
  }
}

Referencia de Hooks

useEmailVerification

El hook principal para la verificación de correo:

const {
  verify,      // Function to verify an email
  result,      // Verification result object
  isLoading,   // Loading state
  error,       // Error object if verification failed
  reset,       // Reset the state
} = useEmailVerification(options);

Opciones:

interface UseEmailVerificationOptions {
  // Debounce delay in milliseconds (default: 500)
  debounceMs?: number;

  // Auto-verify on value change
  autoVerify?: boolean;

  // Cache results for this duration (ms)
  cacheDuration?: number;

  // Custom API endpoint
  apiEndpoint?: string;
}

useEmailInput

Un hook conveniente que combina el estado del input con la verificación:

import { useEmailInput } from '@emailverify/react';

function EmailField() {
  const {
    value,
    onChange,
    onBlur,
    verification,
    isValid,
    errorMessage,
  } = useEmailInput({
    debounceMs: 300,
    validateOnBlur: true,
  });

  return (
    <div>
      <input
        type="email"
        value={value}
        onChange={onChange}
        onBlur={onBlur}
      />
      {errorMessage && <span className="error">{errorMessage}</span>}
    </div>
  );
}

Componentes

Componente EmailInput

Un input de correo pre-construido con verificación:

import { EmailInput } from '@emailverify/react';

function MyForm() {
  const handleVerified = (result) => {
    console.log('Verification result:', result);
  };

  return (
    <EmailInput
      name="email"
      label="Email Address"
      placeholder="you@example.com"
      onVerified={handleVerified}
      showValidationStatus
      blockDisposable
      blockRoleBased={false}
      className="custom-input"
    />
  );
}

Props:

PropTipoPor DefectoDescripción
onVerifiedfunction-Callback cuando se completa la verificación
showValidationStatusbooleantrueMostrar indicadores de validación
blockDisposablebooleantrueMostrar error para correos desechables
blockRoleBasedbooleanfalseMostrar error para correos basados en roles
verifyOnBlurbooleantrueVerificar cuando el campo pierde el foco
debounceMsnumber500Retraso de debounce

Integración con Bibliotecas de Formularios

React Hook Form

import { useForm } from 'react-hook-form';
import { useEmailVerification } from '@emailverify/react';

function SignupForm() {
  const {
    register,
    handleSubmit,
    setError,
    clearErrors,
    formState: { errors },
  } = useForm();

  const { verify, isLoading } = useEmailVerification();

  const validateEmail = async (email) => {
    const result = await verify(email);

    if (result.status === 'invalid') {
      setError('email', {
        type: 'validation',
        message: 'Please enter a valid email address',
      });
      return false;
    }

    if (result.result?.disposable) {
      setError('email', {
        type: 'validation',
        message: 'Disposable emails are not allowed',
      });
      return false;
    }

    clearErrors('email');
    return true;
  };

  const onSubmit = async (data) => {
    const isValid = await validateEmail(data.email);
    if (!isValid) return;

    // Proceed with form submission
    console.log('Submitting:', data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        type="email"
        {...register('email', {
          required: 'Email is required',
          pattern: {
            value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
            message: 'Invalid email format',
          },
        })}
        onBlur={(e) => validateEmail(e.target.value)}
      />
      {errors.email && <span>{errors.email.message}</span>}
      {isLoading && <span>Verifying...</span>}

      <button type="submit">Submit</button>
    </form>
  );
}

Formik

import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
import { useEmailVerification } from '@emailverify/react';

function SignupForm() {
  const { verify } = useEmailVerification();

  const validationSchema = Yup.object({
    email: Yup.string()
      .email('Invalid email format')
      .required('Email is required')
      .test('email-verification', 'Invalid email address', async (value) => {
        if (!value) return false;
        const result = await verify(value);
        return result.status === 'valid';
      }),
  });

  return (
    <Formik
      initialValues={{ email: '' }}
      validationSchema={validationSchema}
      onSubmit={(values) => console.log(values)}
    >
      {({ isSubmitting, isValidating }) => (
        <Form>
          <Field type="email" name="email" />
          <ErrorMessage name="email" component="span" className="error" />
          {isValidating && <span>Verifying...</span>}

          <button type="submit" disabled={isSubmitting || isValidating}>
            Submit
          </button>
        </Form>
      )}
    </Formik>
  );
}

Zod + React Hook Form

import { z } from 'zod';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useEmailVerification } from '@emailverify/react';

const schema = z.object({
  email: z.string().email('Invalid email format'),
  name: z.string().min(2, 'Name must be at least 2 characters'),
});

type FormData = z.infer<typeof schema>;

function SignupForm() {
  const { verify, result } = useEmailVerification();

  const {
    register,
    handleSubmit,
    formState: { errors },
    setError,
  } = useForm<FormData>({
    resolver: zodResolver(schema),
  });

  const onSubmit = async (data: FormData) => {
    // Verify email before submission
    const verification = await verify(data.email);

    if (verification.status !== 'valid') {
      setError('email', {
        type: 'manual',
        message: 'Please enter a valid email address',
      });
      return;
    }

    // Submit form
    console.log('Submitting:', data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input type="email" {...register('email')} />
      {errors.email && <span>{errors.email.message}</span>}

      <input type="text" {...register('name')} />
      {errors.name && <span>{errors.name.message}</span>}

      <button type="submit">Submit</button>
    </form>
  );
}

Debouncing y Rendimiento

Debouncing Integrado

El hook incluye debouncing por defecto:

const { verify } = useEmailVerification({
  debounceMs: 500, // Wait 500ms after user stops typing
});

// Verify on every keystroke (debounced internally)
<input
  type="email"
  onChange={(e) => verify(e.target.value)}
/>

Debouncing Manual

Para más control, use su propio debouncing:

import { useDeferredValue, useEffect } from 'react';

function EmailField() {
  const [email, setEmail] = useState('');
  const deferredEmail = useDeferredValue(email);
  const { verify, result } = useEmailVerification();

  useEffect(() => {
    if (deferredEmail && deferredEmail.includes('@')) {
      verify(deferredEmail);
    }
  }, [deferredEmail]);

  return (
    <input
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  );
}

Almacenamiento en Caché de Resultados

Almacene en caché los resultados de verificación para evitar llamadas a API redundantes:

const { verify } = useEmailVerification({
  cacheDuration: 3600000, // Cache for 1 hour
});

Estilos

Clases CSS

El componente EmailInput aplica estas clases:

/* Container */
.bv-email-input { }

/* Input field */
.bv-email-input__field { }
.bv-email-input__field--valid { }
.bv-email-input__field--invalid { }
.bv-email-input__field--loading { }

/* Status indicators */
.bv-email-input__status { }
.bv-email-input__status--valid { }
.bv-email-input__status--invalid { }
.bv-email-input__status--warning { }

/* Error message */
.bv-email-input__error { }

Ejemplo de Estilos Personalizados

.bv-email-input__field {
  padding: 12px 16px;
  border: 2px solid #e2e8f0;
  border-radius: 8px;
  font-size: 16px;
  transition: border-color 0.2s;
}

.bv-email-input__field:focus {
  outline: none;
  border-color: #3182ce;
}

.bv-email-input__field--valid {
  border-color: #48bb78;
}

.bv-email-input__field--invalid {
  border-color: #f56565;
}

.bv-email-input__status {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 14px;
  margin-top: 4px;
}

.bv-email-input__status--valid {
  color: #48bb78;
}

.bv-email-input__status--invalid {
  color: #f56565;
}

Tailwind CSS

<EmailInput
  className="w-full px-4 py-3 border-2 rounded-lg focus:ring-2 focus:ring-blue-500"
  inputClassName="data-[valid]:border-green-500 data-[invalid]:border-red-500"
  statusClassName="text-sm mt-1"
/>

Soporte de TypeScript

Soporte completo de TypeScript con tipos exportados:

import type {
  VerificationResult,
  EmailVerificationOptions,
  UseEmailVerificationReturn,
} from '@emailverify/react';

interface FormState {
  email: string;
  verification: VerificationResult | null;
}

function useSignupForm(): FormState {
  const [email, setEmail] = useState('');
  const { result } = useEmailVerification();

  return {
    email,
    verification: result,
  };
}

Definiciones de Tipos

interface VerificationResult {
  email: string;
  status: 'valid' | 'invalid' | 'unknown' | 'accept_all';
  result: {
    deliverable: boolean;
    valid_format: boolean;
    valid_domain: boolean;
    valid_mx: boolean;
    disposable: boolean;
    role: boolean;
    catchall: boolean;
    free: boolean;
    smtp_valid: boolean;
  };
  score: number;
  reason: string | null;
}

interface UseEmailVerificationReturn {
  verify: (email: string) => Promise<VerificationResult>;
  result: VerificationResult | null;
  isLoading: boolean;
  error: Error | null;
  reset: () => void;
}

Mejores Prácticas

1. Verifique al Perder el Foco, No en Cada Pulsación de Tecla

// ✅ Bueno - Verificar cuando el usuario termina de escribir
<input
  type="email"
  onBlur={(e) => verify(e.target.value)}
/>

// ❌ Evite - Demasiadas llamadas a API
<input
  type="email"
  onChange={(e) => verify(e.target.value)} // Without debouncing
/>

2. Muestre Retroalimentación Clara

function EmailStatus({ result, isLoading }) {
  if (isLoading) {
    return <span className="text-gray-500">Checking email...</span>;
  }

  if (!result) return null;

  const messages = {
    valid: { text: '✓ Valid email', className: 'text-green-600' },
    invalid: { text: '✗ Invalid email', className: 'text-red-600' },
    unknown: { text: '? Could not verify', className: 'text-yellow-600' },
  };

  const { text, className } = messages[result.status] || {};

  return <span className={className}>{text}</span>;
}

3. No Bloquee el Envío del Formulario

Permita el envío incluso si la verificación está pendiente:

function handleSubmit(data) {
  if (verificationResult?.status === 'invalid') {
    // Show error but don't block
    showWarning('Email may be invalid');
  }

  // Proceed with submission
  submitForm(data);
}

4. Maneje Errores de Red

function EmailField() {
  const { verify, result, error, isLoading } = useEmailVerification();

  return (
    <div>
      <input type="email" onBlur={(e) => verify(e.target.value)} />

      {error && (
        <span className="text-yellow-600">
          Could not verify email. Proceeding anyway.
        </span>
      )}
    </div>
  );
}

Recursos Relacionados

On this page