EmailVerify LogoEmailVerify

React

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

Fügen Sie Echtzeit-E-Mail-Verifizierung zu Ihren React Anwendungen hinzu. Validieren Sie E-Mails während der Eingabe, verhindern Sie ungültige Übermittlungen, und verbessern Sie die Formular-UX.

Installation

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

Schnellstart

Basic Email Input with 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">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>
  );
}

Provider Setup

Wrap your app with the EmailVerify provider:

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

Never expose your API key in client-side code. Always verify emails through your backend.

Backend API Route

Create a secure API endpoint for email verification:

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

Hooks Reference

useEmailVerification

The main hook for email verification:

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

Options:

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

A convenient hook that combines input state with verification:

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

Komponenten

EmailInput Component

A pre-built email input with verification:

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:

PropTypeDefaultDescription
onVerifiedfunction-Callback when verification completes
showValidationStatusbooleantrueShow validation indicators
blockDisposablebooleantrueShow error for disposable emails
blockRoleBasedbooleanfalseShow error for role-based emails
verifyOnBlurbooleantrueVerify when field loses focus
debounceMsnumber500Debounce delay

Form Library Integration

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 and Performance

Built-in Debouncing

The hook includes debouncing by default:

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

Manual Debouncing

For more control, use your own 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)}
    />
  );
}

Zwischenspeicherung Results

Cache verification results to avoid redundant API calls:

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

Styling

CSS Classes

The EmailInput component applies these classes:

/* 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 { }

Custom Styling Example

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

TypeScript Support

Full TypeScript support with exported types:

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

Type Definitions

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

Best Practices

1. Verify on Blur, Not Every Keystroke

// ✅ Good - Verify when user finishes typing
<input
  type="email"
  onBlur={(e) => verify(e.target.value)}
/>

// ❌ Avoid - Too many API calls
<input
  type="email"
  onChange={(e) => verify(e.target.value)} // Without debouncing
/>

2. Show Clear Feedback

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. Don't Block Form Submission

Allow submission even if verification is pending:

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

  // Proceed with submission
  submitForm(data);
}

4. Handle Network Errors

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

Verwandte Ressourcen

On this page