Carl Rippon

Building SPAs

Carl Rippon
BlogBooks / CoursesAbout
This site uses cookies. Click here to find out more

Custom validation rules in React Hook Form

May 12, 2020
typescriptreact

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.

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.

Did you find this post useful?

Let me know by sharing it on Twitter.
Click here to share this post on Twitter

If you to learn more about using TypeScript with React, you may find my course useful:

Using TypeScript with React

Find out more