DEV Community

Cover image for React Hook Form
mai-mohamed
mai-mohamed

Posted on

React Hook Form

React hook form is a tiny library without any other dependencies. It is easy to use which requires us to write fewer lines of code compared to other libraries.

1. Why Not Other React Library Forms?

  • Performance is important. This is a tiny library without any dependencies.
  • Reduces the code to handle forms, with less complexity due to the Hooks.
  • Minimizes the number of re-renders and faster mount.

2. Installation

It's the time to make our forms powerful with the use of React Hook Forms! Open your terminal and then execute the following commands which makes a new React project:

npx create-react-app react-hook-form-demo
cd react-hook-form-demo
npm install react-hook-form
npm start

At the end of the article we will be able to create a simple registration form like this

let's start

3. Basic form


Assume that we have a simple form with a user name input field and logs the data on console after submission

 const App=()=> {
  return (
    <form>
      <input type="text" placeholder="user name"/>
      <button type="submit">submit</button>
    </form>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Time to import react hook form

import { useForm } from "react-hook-form";

const App = () => {
  const { register, handleSubmit } = useForm();
  const onSubmit = (data) => console.log(data);
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input type="text" placeholder="user name" {...register("userName")} />
      <button type="submit">submit</button>
    </form>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

After submittion we got the consoled data but what are those new words (useForm , register )

Before we move ahead we need to know how this library works,

useForm

It is custom hook for managing forms.
This is one of those functions which you will be calling first before you apply any handling logic to your existing forms. It returns an object containing some properties. For now, you only need register and handleSubmit

register

Allows you to register an input ref and apply validation rules into React Hook Form.

handleSubmit

This function will received the form data if form validation is successful.

4.Adding default values (initial values)

It is common to initialize a form by passing defaultValues to useForm.

 const { register, handleSubmit } = useForm({
    defaultValues: {
      userName: "Mai",
    }
  });
Enter fullscreen mode Exit fullscreen mode

5. Basic validation


Assume that we need to validate this user name input to be a required field and must be at least 3 characters

 import { useForm } from "react-hook-form";

const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({ mode: "onChange" });
  const onSubmit = (data) => console.log(data);
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        type="text"
        placeholder="user name"
        {...register("userName", {
          required: true,
          minLength: {
            value: 3,
          },
        })}
      />
      {errors.userName?.type === "required" && (
        <small>user name is required</small>
      )}
      {errors.userName?.type === "minLength" && (
        <small>user name must be atleast 3</small>
      )}
      <button type="submit">submit</button>
    </form>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

React Hook Form provides an errors object to show you the errors in the form.

5. Adding nested fields


Assume that user should enter his address throw two nested fields (country , city)

the final view should be like this

{userName:"toty",
 address:{country:"x",city:"y"}
}

Enter fullscreen mode Exit fullscreen mode
 import { useForm } from "react-hook-form";

const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({ mode: "onChange" });
  const onSubmit = (data) => console.log(data);
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        type="text"
        placeholder="user name"
        {...register("userName", {
          required: true,
          minLength: {
            value: 3,
          },
        })}
      />
      {errors.userName?.type === "required" && (
        <small>user name is required</small>
      )}
      {errors.userName?.type === "minLength" && (
        <small>user name must be atleast 3</small>
      )}

      <input
        type="text"
        placeholder="country"
        {...register("address.country", {
          required: true,
        })}
      />
      <input
        type="text"
        placeholder="city"
        {...register("address.city", {
          required: true,
        })}
      />
      <button type="submit">submit</button>
    </form>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Wooow It is soo easy !!

alt text
But the code is little long so let's make a small refactor for moving the input to be a shared component and also using react bootstrap

6. Integration with react bootstrap

import { Form } from "react-bootstrap";
const Input = ({
  label,
  type,
  placeholder,
  controls,
  errorMsg,
  disabled,
}) => {
  return (
    <div className="mb-3">
      {label && <Form.Label> 
      {label}</Form.Label>}
      <Form.Control
        {...controls}
        type={type}
        placeholder={placeholder}
        disabled={disabled}
      />
      {errorMsg && <small> 
      {errorMsg}</small>}
    </div>
  );
};
export default Input;
Enter fullscreen mode Exit fullscreen mode

and the main component after refactoring should be like this

    <Input
      label="User Name"                
      type="text"
       placeholder="enter your user name"
       controls={register("userName", {
       required: true,
       minLength: {
       value: 3,
       },
        })}
      errorMsg={
      errors.userName?.type === "required" &&
      "user name is required"
       }

      />
Enter fullscreen mode Exit fullscreen mode

7. Integration with third party libraries

Assume that our third party library is React select
npm install react-select
first we need to add a shared component for react select

import React from "react";
import Select from "react-select";
import { Controller } from "react-hook-form";

const InputSelect = ({
  options,
  label,
  control,
  controls,
  name,
  errorMsg,
  placeholder,
  asterick,
}) => {
  return (
    <>
      <label>
        {label} {asterick && <span>*</span>}
      </label>
      <Controller
        name={name}
        isClearable
        control={control}
        {...controls}
        render={({ field }) => (
          <Select
            {...field}
            options={options}
            placeholder={placeholder}
          />
        )}
      />
      {errorMsg && <small>{errorMsg}</small>}
    </>
  );
};
export default InputSelect;

Enter fullscreen mode Exit fullscreen mode

But what Controller means
It is a wrapper component from react hook form that makes it easier for you to work with third party libraries.

and now we can use this select in our main component like this

const genderOptions = [
    { value: "male", label: "Male" },
    { value: "female", label: "Female" },
  ];
Enter fullscreen mode Exit fullscreen mode
<InputSelect
  control={control}
  options={genderOptions}
  placeholder="Gender"
  asterick={true}
  label="Gender"
  name="gender"
  controls={register("gender", {
  required: true,
   })}
  errorMsg={
  errors?.gender?.type === "required" && 
  "gender is required"
    }
   />
Enter fullscreen mode Exit fullscreen mode

stay tuned for the next article to complete our journey in react hook forms
and don't forget your feed back.

Top comments (3)

Collapse
 
hasnaindev profile image
Muhammad Hasnain

I'm here for the SpongeBob.

Collapse
 
bluebill1049 profile image
Bill

Thank you for writing this blog post.

Collapse
 
ahmednoureldinmohamed profile image
AhmedNourElDinMohamed

*Very useful article Thanxs *