Frontend & UI

How to Build a "Smart" Email Input in React

By Yahya Lazrek • 6 min read

Forms are the highest-friction part of any SaaS application. If you make email validation too strict (like requiring double opt-in), your conversion rate plummets. If you make it too loose, your database fills with temp-mail.org addresses and fat-finger typos like user@gmil.com.

The "Smart" Input Approach

The best modern signup flows do the heavy lifting in the background. Instead of waiting for an email to bounce, we can validate the email in real-time when the user clicks out of the input field (the onBlur event).

Here is how to build a React component that:

  • Pings live DNS/MX records to ensure the domain exists.
  • Blocks known disposable and role-based emails.
  • Autocorrects typos with a 1-click "Did you mean?" UI.

The Code (Tailwind + React Hooks)

First, get your free validation API key from EmailGuard, then drop this component into your Next.js or React app:

import React, { useState } from 'react';

export default function SmartEmailInput() {
  const [email, setEmail] = useState('');
  const [status, setStatus] = useState('idle');
  const [message, setMessage] = useState('');
  const [suggestion, setSuggestion] = useState(null);

  const validateEmail = async (emailToTest) => {
    setStatus('loading');
    
    // Call the EmailGuard Edge API
    const res = await fetch(`https://emailguard.../?email=${emailToTest}`);
    const data = await res.json();

    if (data.checks.is_disposable) {
      setStatus('error');
      setMessage('Please use a permanent email.');
    } else if (data.checks.is_typo && data.suggestion) {
      setStatus('error');
      setSuggestion(data.suggestion);
      setMessage(`Did you mean ${data.suggestion}?`);
    } else {
      setStatus('success');
    }
  };

  return (
    <div className="flex flex-col w-full sm:w-80 gap-2">
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        onBlur={() => validateEmail(email)}
        className="w-full px-4 py-2 border rounded-lg"
      />
      {status === 'error' && suggestion && (
        <button onClick={() => setEmail(suggestion)}>
           {message} (Click to fix)
        </button>
      )}
    </div>
  );
}

Why `onBlur` is the Magic Key

Notice that we don't validate onChange. If you ping an API on every keystroke, you will burn through your API quota in seconds and slow down the browser. By attaching the validation to onBlur, the check only happens exactly once: right after the user finishes typing.

Want the full, production-ready code?

I open-sourced the complete React component with full error handling and Tailwind styling. Grab the code and your free API key below.