Custom validation rules in React Hook Form
In the last post we used React Hook Form to build a form to capture a name, an email address, and a score. We implemented required validation rules on all the fields.
- Getting started with React Hook Form with TypeScript
- Custom validation rules in React Hook Form (this post)
- Master-detail forms with React Hook Form
In this post, we will implement more complex validation rules on that same form.
Multiple validation rules on a field
We’ll start by adding additional rules to the score field. It already has a required validation rule, but now we want to ensure the score is between 0 and 100:
<input
type="number"
id="score"
name="score"
ref={register({
required: true,
min: 0, max: 100 })}
/>
We can implement this using the min
and max
standard rules with React Hook Form.
We can also render useful validation error messages when these rules are broken:
{
errors.score && errors.score.type === "min" && (
<div className="error">Your score must be at least 0</div>
);
}
{
errors.score && errors.score.type === "max" && (
<div className="error">Your score must be no more than 100</div>
);
}
We use the type
property to determine which rule the validation error is for and then render an appropriate message.
Custom validation rules
Let’s implement another rule on the score field. Now we want to ensure the score is an even number. This rule doesn’t exist in React Hook Form, so we need to implement a custom validation rule. Here’s the function for the rule:
const isEven = (score: number) => score % 2 === 0;
Here’s how we can wire this rule up to the score field:
<input
type="number"
id="score"
name="score"
ref={register({
required: true,
min: 0,
max: 100,
validate: isEven })}
/>
So, we set the validate
property in the register
functions object parameter to the validator function. A custom validator function for React Hook Form takes in the value of the field and returns true
if the rule passes and false
if the rule fails.
Let’s render an error message if this rule fails:
{
errors.score && errors.score.type === "validate" && (
<div className="error">Your score must be and even number</div>
);
}
The type
property for a custom validation rule error is "validate"
.
Asynchronous validation
Some custom validation rules will require a web service call to a backend to carry out the check. The validator functions for these rules are asynchronous. Let’s see how we implement an asynchronous validation rule in React Hook Form.
We’ll implement a rule on the email address to check that it is unique. We will fake the backend check with the following emailIsUnique
function:
const emailIsUnique = async (email: string) => {
await wait(1000);
return email !== "someone@somewhere.com";
};
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
We wire custom asynchronous validator functions up the same as synchronous validator functions:
<input
type="email"
id="email"
name="email"
ref={register({
required: true,
validate: emailIsUnique })}
/>
Let’s render an error message if this rule fails:
{
errors.email && errors.email.type === "validate" && (
<div className="error">This email address already exists</div>
);
}
A working example of this form is available in CodeSandbox
Wrap up
It’s super easy to implement custom validation rules with React Hook Form. Asynchronous custom validation rules are also supported.
In the next post, we’ll dive into how you can implement master detail forms with React Hook Form.
If you to learn more about using TypeScript with React, you may find my course useful: