Proper email validation in React Hook Form is vital for maintaining clean data and a smooth user experience. You'll find five distinct methods for setting it up, each with code examples. We'll also cover the drawbacks of these approaches and demonstrate how Abstract API provides a more robust solution.
How to Implement Email Validation in React Hook Form
This section details four different ways to set up email validation in React Hook Form. Each method includes a description of its function and a corresponding code example.
HTML5 Native Constraint Validation
React Hook Form can delegate the validation process to the browser. To do this, you enable the "shouldUseNativeValidation" option when you initialize the form with the "useForm" hook, as shown in the React Hook Form docs.
You must also keep the input element’s "type" attribute as "email" and include the "required" attribute. The browser then performs the validation, focuses on the first invalid field, and provides the error message.
const {register, handleSubmit} = useForm({mode: 'onBlur', shouldUseNativeValidation: true})
<form noValidate onSubmit={handleSubmit(onSubmit)}>
<input type="email" required {...register('email')}/>
<button>Submit</button>
</form>
Regular Expression Pattern Rule
You can attach a "pattern" object directly to the input field's registration. React Hook Form incorporates this pattern into its standard validation pipeline alongside other rules you define, a method discussed in a Stack Overflow question.
A well-defined regular expression, combined with a custom error message, is sufficient for most common validation scenarios according to a dev.to article.
const {register, formState:{errors}} = useForm()
<input
{...register('email', {
required: 'email is mandatory',
pattern: {value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message: 'invalid'}
})}
/>
{errors.email?.message}
Custom Validator Function
For more complex validation logic, you can supply a custom function to the "validate" property. This is useful for non-trivial checks like MX record lookups or checks against a blocklist of disposable domains, a technique covered in an Abstract API guide.
React Hook Form interprets any truthy return value from the function, or a resolved Promise, as a successful validation. If the function returns a string, it is used as the error message.
const {register} = useForm({mode:'onChange'})
<input
{...register('email', {
validate: async value => {
const res = await fetch('/api/validate-email?e=' + encodeURIComponent(value))
const {ok, reason} = await res.json()
return ok || reason // string → error message
}
})}
/>
Schema-Based Validation with a Resolver
This approach moves the validation rules outside of the UI component. A schema library, such as Yup or Zod, defines the data shape and rules, and a resolver connects it to React Hook Form.
This method helps keep the component code lean. It also supports complex data transformations and allows you to reuse the same validation schema on your server, as demonstrated on Jason Watmore's blog.
import * as Yup from 'yup'
const schema = Yup.object({email: Yup.string().required().email()})
const {register, formState:{errors}} = useForm({resolver: yupResolver(schema)})
<input {...register('email')}/> {errors.email?.message}
Challenges of Email Validation in React Hook Form
While these methods are functional, they introduce several significant problems that can compromise data quality and create inconsistent user experiences across different browsers.
- Regular expressions and native HTML5 validation cannot perfectly parse RFC 5322 grammar. This forces a choice between false positives that accept invalid emails and false negatives that block valid ones, especially with edge cases.
- Native HTML5 validation delegates control to the browser. Since each browser implements different patterns and error reports, this approach creates inconsistent behavior. A form may validate in one browser but fail in another.
- All four methods operate on the client side, so a user can bypass them. They only confirm syntax, not deliverability. An email that passes validation can still bounce because the check does not verify mailbox existence.
- The regex pattern rule can fail silently. If a pattern from a JSON string fails to convert to a RegExp object, React Hook Form ignores the rule, which creates a false sense of security.
Validate Emails with Abstract API
Validate user emails to improve data quality and ensure your messages reach the inbox.
Get started for free
How Abstract API Handles Email Validation in React Hook Form
Abstract API addresses the core weaknesses of traditional methods through comprehensive, server-side checks that confirm an email's deliverability.
- It pushes validation to a remote endpoint for deep analysis. This process includes syntax checks, typo correction, and real-time MX and SMTP interrogation.
- It determines if an address can actually receive mail and assesses its risk level, a capability React Hook Form lacks on its own.
- It integrates with React Hook Form to defer expensive network and DNS work. The form first performs a local pattern check, then makes an async call to the API for a definitive result.
- The API response provides detailed signals like deliverability status and a quality score. It also adds flags for disposable or role-based addresses to allow for nuanced form logic.
How to Set Up Abstract API in Your Project
Once you understand Abstract’s capabilities, the process to add its email validation API to your project is simple. Follow these steps to prepare your development environment:
- Sign up at Abstract, create an Email Verification API instance, and copy your API key.
- Install react-hook-form and axios with npm, or use the native fetch method.
- Add your key to a .env file as REACT_APP_ABSTRACT_EMAIL_KEY and restart the development server.
- Create a utility file, such as utils/validateEmail.js, to construct the API request URL.
- Import your validation function into the form component and call it within handleSubmit. Use the response to manage form state or show errors.
- Optionally, implement a cache or throttle to prevent API calls on every keystroke.
Sample Email Validation Implementation with Abstract API
The code below demonstrates a practical implementation. It defines a `Signup` component that uses a custom `validateEmail` function. This function sends the user's email to the Abstract API endpoint. Inside the `onSubmit` handler, the form awaits the validation result. If the API response shows the email is not "DELIVERABLE" or comes from a disposable provider, the form uses React Hook Form’s `setError` function to block the submission and show an error. Otherwise, the signup process continues.
import { useForm } from 'react-hook-form';
import axios from 'axios';
const key = import.meta.env.VITE_ABSTRACT_KEY;
async function validateEmail(email) {
const url = `https://emailvalidation.abstractapi.com/v1/?api_key=${key}&email=${encodeURIComponent(email)}`;
const { data } = await axios.get(url);
return data;
}
export default function Signup() {
const { register, handleSubmit, setError } = useForm();
const onSubmit = async ({ email }) => {
const res = await validateEmail(email);
if (res.deliverability !== 'DELIVERABLE' || res.is_disposable_email.value) {
return setError('email', { type: 'server', message: 'Undeliverable or disposable' });
}
// continue with createUser(...)
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('email', { required: true, pattern: /^\S+@\S+\.\S+$/ })} />
<button type="submit">Sign up</button>
</form>
);
}
A successful API call returns a detailed JSON object like this:
{
"email": "johnsmith@gmail.com",
"autocorrect": "",
"deliverability": "DELIVERABLE",
"quality_score": 0.9,
"is_valid_format": { "value": true, "text": "TRUE" },
"is_free_email": { "value": true, "text": "TRUE" },
"is_disposable_email": { "value": false, "text": "FALSE" },
"is_role_email": { "value": false, "text": "FALSE" },
"is_mx_found": { "value": true, "text": "TRUE" },
"is_smtp_valid": { "value": true, "text": "TRUE" }
}
Key fields include `deliverability`, which confirms if an address accepts mail, and `quality_score`, which estimates bounce risk. The boolean `is_*` fields expose disposable, role-based, or other high-risk addresses. This allows you to create nuanced validation logic.
Final Thoughts
Traditional email validation often fails to detect undeliverable or high-risk addresses. Abstract API overcomes these limits with deep, server-side checks that confirm an email's actual deliverability and quality. For robust email validation, consider a free account with Abstract API to get your API key and reliably validate user emails.
Validate Emails with Abstract API
Stop bad emails at the source by adding effective, real-time email validation to your forms.
Get started for free