EmailVerify LogoEmailVerify

React

Email checker for React. Real-time validation with hooks, components, and context.

Ajoutez la vérification d'email en temps réel à vos applications React. Validez les emails pendant que les utilisateurs tapent, évitez les soumissions invalides et améliorez l'UX des formulaires.

Installation

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

Démarrage rapide

Champ d'email de base avec validation

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">Vérification...</span>}

        {result?.status === 'invalid' && (
          <span className="error-message">
            Veuillez saisir une adresse email valide
          </span>
        )}

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

        {result?.result?.disposable && (
          <span className="warning-message">
            Veuillez utiliser une adresse email permanente
          </span>
        )}
      </div>

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

Configuration du Provider

Enveloppez votre application avec le provider EmailVerify :

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

function App() {
  return (
    <EmailVerifyProvider
      config={{
        // Les appels API passent par votre backend
        apiEndpoint: '/api/verify-email',
      }}
    >
      <YourApp />
    </EmailVerifyProvider>
  );
}

Ne jamais exposer votre clé API dans le code côté client. Toujours vérifier les emails via votre backend.

Route API Backend

Créez un endpoint API sécurisé pour la vérification d'email :

// pages/api/verify-email.js (Next.js) ou votre route Express
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' });
  }
}

Référence des Hooks

useEmailVerification

Le hook principal pour la vérification d'email :

const {
  verify,      // Fonction pour vérifier un email
  result,      // Objet résultat de vérification
  isLoading,   // État de chargement
  error,       // Objet d'erreur si la vérification a échoué
  reset,       // Réinitialiser l'état
} = useEmailVerification(options);

Options :

interface UseEmailVerificationOptions {
  // Délai de debounce en millisecondes (par défaut : 500)
  debounceMs?: number;

  // Vérification automatique lors du changement de valeur
  autoVerify?: boolean;

  // Cache des résultats pour cette durée (ms)
  cacheDuration?: number;

  // Endpoint API personnalisé
  apiEndpoint?: string;
}

useEmailInput

Un hook pratique qui combine l'état de l'input avec la vérification :

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>
  );
}

Composants

Composant EmailInput

Un champ d'email pré-construit avec vérification :

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

function MyForm() {
  const handleVerified = (result) => {
    console.log('Résultat de vérification :', result);
  };

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

Props :

PropTypeDéfautDescription
onVerifiedfunction-Callback lorsque la vérification est terminée
showValidationStatusbooleantrueAfficher les indicateurs de validation
blockDisposablebooleantrueAfficher une erreur pour les emails jetables
blockRoleBasedbooleanfalseAfficher une erreur pour les emails de rôle
verifyOnBlurbooleantrueVérifier lorsque le champ perd le focus
debounceMsnumber500Délai de debounce

Intégration avec les bibliothèques de formulaires

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: 'Veuillez saisir une adresse email valide',
      });
      return false;
    }

    if (result.result?.disposable) {
      setError('email', {
        type: 'validation',
        message: 'Les emails jetables ne sont pas autorisés',
      });
      return false;
    }

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

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

    // Poursuivre la soumission du formulaire
    console.log('Soumission :', data);
  };

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

      <button type="submit">Soumettre</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('Format d\'email invalide')
      .required('Email requis')
      .test('email-verification', 'Adresse email invalide', 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>Vérification...</span>}

          <button type="submit" disabled={isSubmitting || isValidating}>
            Soumettre
          </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('Format d\'email invalide'),
  name: z.string().min(2, 'Le nom doit contenir au moins 2 caractères'),
});

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) => {
    // Vérifier l'email avant la soumission
    const verification = await verify(data.email);

    if (verification.status !== 'valid') {
      setError('email', {
        type: 'manual',
        message: 'Veuillez saisir une adresse email valide',
      });
      return;
    }

    // Soumettre le formulaire
    console.log('Soumission :', 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">Soumettre</button>
    </form>
  );
}

Debouncing et performance

Debouncing intégré

Le hook inclut le debouncing par défaut :

const { verify } = useEmailVerification({
  debounceMs: 500, // Attendre 500ms après que l'utilisateur arrête de taper
});

// Vérifier à chaque frappe (debounced en interne)
<input
  type="email"
  onChange={(e) => verify(e.target.value)}
/>

Debouncing manuel

Pour plus de contrôle, utilisez votre propre 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)}
    />
  );
}

Cache des résultats

Mettez en cache les résultats de vérification pour éviter les appels API redondants :

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

Style

Classes CSS

Le composant EmailInput applique ces classes :

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

/* Champ de saisie */
.bv-email-input__field { }
.bv-email-input__field--valid { }
.bv-email-input__field--invalid { }
.bv-email-input__field--loading { }

/* Indicateurs de statut */
.bv-email-input__status { }
.bv-email-input__status--valid { }
.bv-email-input__status--invalid { }
.bv-email-input__status--warning { }

/* Message d'erreur */
.bv-email-input__error { }

Exemple de style personnalisé

.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"
/>

Support TypeScript

Support TypeScript complet avec types exportés :

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,
  };
}

Définitions de types

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;
}

Bonnes pratiques

1. Vérifier lors de la perte de focus, pas à chaque frappe

// ✅ Bon - Vérifier lorsque l'utilisateur finit de taper
<input
  type="email"
  onBlur={(e) => verify(e.target.value)}
/>

// ❌ Éviter - Trop d'appels API
<input
  type="email"
  onChange={(e) => verify(e.target.value)} // Sans debouncing
/>

2. Afficher un retour clair

function EmailStatus({ result, isLoading }) {
  if (isLoading) {
    return <span className="text-gray-500">Vérification de l'email...</span>;
  }

  if (!result) return null;

  const messages = {
    valid: { text: '✓ Email valide', className: 'text-green-600' },
    invalid: { text: '✗ Email invalide', className: 'text-red-600' },
    unknown: { text: '? Impossible de vérifier', className: 'text-yellow-600' },
  };

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

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

3. Ne pas bloquer la soumission du formulaire

Autoriser la soumission même si la vérification est en attente :

function handleSubmit(data) {
  if (verificationResult?.status === 'invalid') {
    // Afficher un avertissement mais ne pas bloquer
    showWarning('L\'email peut être invalide');
  }

  // Poursuivre la soumission
  submitForm(data);
}

4. Gérer les erreurs réseau

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">
          Impossible de vérifier l'email. Poursuite quand même.
        </span>
      )}
    </div>
  );
}

Ressources associées

On this page