P M A J E W S K I

Please Wait For Loading

Simplify Your React Forms with React Hook Form and Yup - Software Developer's Tour

react hook form

Simplify Your React Forms with React Hook Form and Yup

Here we are! The first post about frontend technology has been written. Until now, only backend and DevOps topics have been covered.

Today I want to show you one of the top libraries that allows us to manage forms easily.

React Hook Form and Yup

What is React Hook Form?

It’s one of the most frequently used library to manage forms with React. As we can read on the project’s site 

Performance is one of the primary reasons why this library was created.

https://react-hook-form.com/faqs

What is Yup?

Yup is a library used for creating schemas that help in parsing and validating values at runtime.

npm install react-hook-form
npm install @hookform/resolvers yup

I have created simple form using bootstrap.

simple form

In a standard case, we would create a useState or useRef for each field. It would result in a massive amount of code. However, it’s a good approach when you are new to React and still learning. By implementing it yourself, you will learn how React works and how to solve basic problems that surprise beginners. Okay, let’s get back to the main thread.

I have created React with typescript, so let’s create a type that defines our form.

type FormData = {
    firstName: string;
    lastName: string;
    age: number;
    email: string;
    password: string;
}

Then is good time to define our validation schema for this model.

const schema: ObjectSchema<FormData> = yup
    .object({
        firstName: yup.string().required("FirstName cannot be empty"),
        lastName: yup.string().required("LastName cannot be empty"),
        age: yup.number().positive("Age must be positive number").integer().required("Age cannot be empty").typeError("Age must be a number"),
        email: yup.string().required("Email cannot be empty").matches(RegexConsts.email, "Email must contain @ and . characters"),
        password: yup.string().required("Password cannot be empty"),
    });

Yup provides many validation methods. I won’t waste your time, so here I will only touch on the matches method.

Matches method allows us to define regex pattern to validate this field. The second parameters means failed validation message.

export const RegexConsts = {
    email: /.*[@].*[.][a-zA-Z]{2,}/
}

React Hook Form validates forms based on configuration, in this case after submitting the form.

validation failed

Custom validation for age

yup.number().positive("Age must be positive number").integer().required("Age cannot be empty").typeError("Age must be a number")
type validation
positive error validation

When validation is successfully completed, the submit method returns our form object with the filled fields.

validation success

The full file looks as presented below

import { useForm } from "react-hook-form"
import { yupResolver } from "@hookform/resolvers/yup"
import * as yup from "yup"
import { RegexConsts } from "../consts/regexConsts"
import { ObjectSchema } from "yup"

type FormData = {
    firstName: string;
    lastName: string;
    age: number;
    email: string;
    password: string;
}

const schema: ObjectSchema<FormData> = yup
    .object({
        firstName: yup.string().required("FirstName cannot be empty"),
        lastName: yup.string().required("LastName cannot be empty"),
        age: yup.number().positive("Age must be positive number").integer().required("Age cannot be empty").typeError("Age must be a number"),
        email: yup.string().required("Email cannot be empty").matches(RegexConsts.email, "Email must contain @ and . characters"),
        password: yup.string().required("Password cannot be empty"),
    });


export default function RegisterForm() {
    const {
        register,
        handleSubmit,
        formState: { errors },
    } = useForm<FormData>({
        resolver: yupResolver(schema),
    })

    const onSubmit = (data: FormData) => console.log(data)

    return (
        <>
            <form className="card p-2" onSubmit={handleSubmit(onSubmit)}>
                <div className="row">
                    <div className="col-md-6 mb-6">
                        <div className="input-group">
                            <label className="w-100">First name
                                <input type="text" className="form-control" {...register("firstName")} />
                            </label>
                            <div className="invalid-feedback d-block">
                                {errors.firstName?.message}
                            </div>
                        </div>
                        <div className="input-group">
                            <label className="w-100">Last name
                                <input type="text" className="form-control" {...register("lastName")} />
                            </label>
                            <div className="invalid-feedback d-block">
                                {errors.lastName?.message}
                            </div>
                        </div>
                        <div className="input-group">
                            <label className="w-100">Age
                                <input type="text" className="form-control" {...register("age")} />
                            </label>
                            <div className="invalid-feedback d-block">
                                {errors.age?.message}
                            </div>
                        </div>
                        <div className="input-group">
                            <label className="w-100">Email
                                <input type="text" className="form-control" {...register("email")} />
                            </label>
                            <div className="invalid-feedback d-block">
                                {errors.email?.message}
                            </div>
                        </div>
                        <div className="input-group">
                            <label className="w-100">Password
                                <input type="password" className="form-control" {...register("password")} />
                            </label>
                            <div className="invalid-feedback d-block">
                                {errors.password?.message}
                            </div>
                        </div>
                    </div>
                    <div className="col-md-6 mb-6">
                        <button type="submit" className="btn btn-outline-success w-100">Send</button>
                    </div>
                </div>
            </form>
        </>
    )
}

I highly recommend using React Hook Form combined with Yup validation in your daily work with React.

leave a comment