React Hook Form Typescript example with Validation

In this tutorial, I will show you how to implement React Hook Form Typescript with Validation and Submit example using Hooks, react-hook-form 7 and Bootstrap 4.

More Practice:
React Custom Hook in Typescript example
React Typescript File Upload example
React Typescript with API call example
React Hooks: JWT Authentication (without Redux) example
React Hooks + Redux: JWT Authentication example

Related Posts:
React Form Validation with Hooks, Material UI | react-hook-form 7
React Table example: CRUD App | react-table 7

Serverless with Firebase:
React Hooks + Firebase Realtime Database: CRUD App
React Hooks + Firestore example: CRUD app

Javascript version: React Hook Form Validation example with react-hook-form 7


Overview of React Hook Form Typescript example

We will implement validation and submit for a React Typescript Form using React Hook Form 7 and Bootstrap 4. The form has:

  • Full Name: required
  • Username: required, from 6 to 20 characters
  • Email: required, email format
  • Password: required, from 6 to 40 characters
  • Confirm Password: required, same as Password
  • Accept Terms Checkbox: required

react-hook-form-typescript-example-validation

Some fields could be wrong:

react-hook-form-typescript-example-submit-error

Successful Submission will look like this:

react-hook-form-typescript-example-submit

Technology

We’re gonna use following modules:

  • react 17/16
  • typescript 4.1.2
  • bootstrap 4
  • react-hook-form 7
  • yup
  • @hookform/resolvers 2.4.0

Setup Project

First we need to install necessary modules.
Open your project root folder, run the command:

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

Open package.json, the dependencies will look like this:

{
  "name": "react-hook-form-typescript",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    ...
    "@types/node": "^12.0.0",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-hook-form": "^7.10.1",
    "react-scripts": "4.0.3",
    "typescript": "^4.1.2",
    "yup": "^0.32.9"
  },
  ...
}

Import Bootstrap 4

Open public/index.html and add following line to <head> tag:

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <link href="//netdna.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
    ...
    <title>React Hook Form Typescript with Validation</title>
  </head>
  <body>
    ...
    <div id="root"></div>
  </body>
</html>

Or you can run command: npm install bootstrap.

Then open src/App.tsx and modify the code inside it as following-

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";

const App: React.FC = () => {
  return (
    ...
  );
}

export default App;

React Hook Form Typescript Register Type

We continue to create Type for useForm – register method later.

import ...

type UserSubmitForm = {
  fullname: string;
  username: string;
  email: string;
  password: string;
  confirmPassword: string;
  acceptTerms: boolean;
};

const App: React.FC = () => {
  ...
}

React Hook Form Typescript with Validation

The React Typescript component contains Form Validation example built with the React Hook Form library version 7.

Open src/App.tsx, we’re gonna import necessary library first:

import React from 'react';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';

Next we use Yup schema validation library for Form validation rules:

const App: React.FC = () => {
  const validationSchema = Yup.object().shape({
    fullname: Yup.string().required('Fullname is required'),
    username: Yup.string()
      .required('Username is required')
      .min(6, 'Username must be at least 6 characters')
      .max(20, 'Username must not exceed 20 characters'),
    email: Yup.string()
      .required('Email is required')
      .email('Email is invalid'),
    password: Yup.string()
      .required('Password is required')
      .min(6, 'Password must be at least 6 characters')
      .max(40, 'Password must not exceed 40 characters'),
    confirmPassword: Yup.string()
      .required('Confirm Password is required')
      .oneOf([Yup.ref('password'), null], 'Confirm Password does not match'),
    acceptTerms: Yup.bool().oneOf([true], 'Accept Terms is required')
  });

  ...
}

Then we pass the rules to the React Hook Form useForm() function using yupResolver() function from react-hook-form/resolvers library.

const App: React.FC = () => {
  const validationSchema = ...

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors }
  } = useForm<UserSubmitForm>({
    resolver: yupResolver(validationSchema)
  });
  ...
}

The useForm() hook function returns an object that we use following methods:

  • register: register inputs
  • handleSubmit: handle form submit
  • reset:reset the form

The object also has formState that contains errors.

When the form is valid and submitted, onSubmit() method is called and the form data will show in console:

const App: React.FC = () => {
  ...
  const onSubmit = (data: UserSubmitForm) => {
    console.log(JSON.stringify(data, null, 2));
  };
  ...
}

React Hook Form Typescript example

Now we create the form with input fields and validation messages. We register form fields with the React Hook Form by calling the register function above with the field name of input element {...register('fieldname')}.

const App: React.FC = () => {
  ...

  return (
    <div className="register-form">
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className="form-group">
          <label>Full Name</label>
          <input
            type="text"
            {...register('fullname')}
            className={`form-control ${errors.fullname ? 'is-invalid' : ''}`}
          />
          <div className="invalid-feedback">{errors.fullname?.message}</div>
        </div>

        <div className="form-group">
          <label>Username</label>
          <input
            type="text"
            {...register('username')}
            className={`form-control ${errors.username ? 'is-invalid' : ''}`}
          />
          <div className="invalid-feedback">{errors.username?.message}</div>
        </div>

        <div className="form-group">
          <label>Email</label>
          <input
            type="text"
            {...register('email')}
            className={`form-control ${errors.email ? 'is-invalid' : ''}`}
          />
          <div className="invalid-feedback">{errors.email?.message}</div>
        </div>

        <div className="form-group">
          <label>Password</label>
          <input
            type="password"
            {...register('password')}
            className={`form-control ${errors.password ? 'is-invalid' : ''}`}
          />
          <div className="invalid-feedback">{errors.password?.message}</div>
        </div>
        <div className="form-group">
          <label>Confirm Password</label>
          <input
            type="password"
            {...register('confirmPassword')}
            className={`form-control ${
              errors.confirmPassword ? 'is-invalid' : ''
            }`}
          />
          <div className="invalid-feedback">
            {errors.confirmPassword?.message}
          </div>
        </div>

        <div className="form-group form-check">
          <input
            type="checkbox"
            {...register('acceptTerms')}
            className={`form-check-input ${
              errors.acceptTerms ? 'is-invalid' : ''
            }`}
          />
          <label htmlFor="acceptTerms" className="form-check-label">
            I have read and agree to the Terms
          </label>
          <div className="invalid-feedback">{errors.acceptTerms?.message}</div>
        </div>

        <div className="form-group">
          <button type="submit" className="btn btn-primary">
            Register
          </button>
          <button
            type="button"
            onClick={() => reset()}
            className="btn btn-warning float-right"
          >
            Reset
          </button>
        </div>
      </form>
    </div>
  );
};

export default App;

Run React Form Validation Hooks App

You can run our App with command: npm start.
If the process is successful, open Browser with Url: http://localhost:3000/ and check it.

Or run on Stackblitz:

Conclusion

Today we’ve built a React Form Validation using Hooks example successfully with React Hook Form 7 & Bootstrap 4.

You can also use the Form Validation in following posts:
React Typescript with API call example using Hooks and Axios
React Hooks: JWT Authentication (without Redux) example
React Hooks + Redux: JWT Authentication example

More Practice:
React Pagination using Hooks example
React Typescript with API call example
React Typescript File Upload example
React Table example: CRUD App | react-table 7

Serverless with Firebase:
React Hooks + Firebase Realtime Database: CRUD App
React Hooks + Firestore example: CRUD app

Fullstack:
React + Spring Boot + MySQL: CRUD example
React + Spring Boot + PostgreSQL: CRUD example
React + Spring Boot + MongoDB: CRUD example
React + Node + Express + MySQL: CRUD example
React + Node + Express + PostgreSQL example
React Redux + Node + Express + MySQL: CRUD example
React + Node + Express + MongoDB example
React + Django + Rest Framework example

Source Code

You can find the complete source code for this tutorial on Github.

Javascript version: React Hook Form Validation example with react-hook-form 7

3 thoughts to “React Hook Form Typescript example with Validation”

Comments are closed to reduce spam. If you have any question, please send me an email.