Easy Multi-Page Form with React-Router and React-Hook-Form
Tags: react, tutorial, javascript, learning
Published: 2022-05-18 17:15:56

In this tutorial, I'll be showing you how to create a multi-page form – consisting of a <u>Form page</u>, <u>Confirm / Review page</u>, and <u>Complete page</u> only using **react-router** and **react-hook-form**.

**1.** First, let's create our pages/components.
```jsx
// Form

const Form = () => {
  return (
    <div>
      <form onSubmit={onSubmit}>
        <div>
          FirstName: <input type="text" />
        </div>
        <div>
          LastName: <input type="text" />
        </div>
        <div>
          Gender:
          <input type="radio" value="male" /> Male
          <input type="radio" value="female" /> Female
        </div>
        <div>
          Country:
          <select>
            <option value="USA">USA</option>
            <option value="Canada">Canada</option>
            <option value="India">India</option>
          </select>
        </div>
        <button type="submit">Confirm</button>
      </form>
    </div>
  );
};
export default Form;
```
```jsx
// Confirm

const Confirm = () => {
  return (
    <div>
      <p>firstName: </p>
      <p>lastName: </p>
      <p>Gender: </p>
      <p>Country: </p>
      <button>back</button>
      <button>Submit</button>
    </div>
  );
};
export default Confirm;
```
```jsx
// Complete

const Complete = () => {
  return (
    <div>
      <p>Registration successful!</p>
    </div>
  );
};
export default Complete;
```

**2.** Next, by using react-hook-form's [`useForm`](https://react-hook-form.com/api/useform/) we will get the form data from our Form component.
```jsx
const Form = () => {
  const { register, handleSubmit } = useForm();

  const onSubmit = handleSubmit((data) => {
    // logs form data
    console.log(data);
  });

  return (
    <div>
      <form onSubmit={onSubmit}>
        <div>
          FirstName: <input type="text" {...register("firstName")} />
        </div>
        <div>
          LastName: <input type="text" {...register("lastName")} />
        </div>
        <div>
          Gender:
          <input type="radio" value="male" {...register("gender")} /> Male
          <input type="radio" value="female" {...register("gender")} /> Female
        </div>
        <div>
          Country:
          <select {...register("country")}>
            <option value="USA">USA</option>
            <option value="Canada">Canada</option>
            <option value="India">India</option>
          </select>
        </div>
        <button type="submit">Confirm</button>
      </form>
    </div>
  );
};
```
This should show the form data in console on submit.
```
// output would be something like this
{
 firstName: "John"
 lastName: "Doe"
 gender: "male"
 country: "Canada"
}
```
**3.** Pass the data to our Confirm Page using react-router's [`useNavigate`](https://reactrouter.com/docs/en/v6/hooks/use-navigate#usenavigate) <u>state</u> prop.
```jsx
const Form = () => {
  const navigate = useNavigate();
  const { register, handleSubmit } = useForm();

  const onSubmit = handleSubmit((data) => {
    // Pass the form data on state prop when navigating to confirm page.
    navigate("/confirm", { state: data });
  });
 ...
```

**4.** Displaying data on Confirm page -- this time using react-router's [`useLocation`](https://reactrouter.com/docs/en/v6/hooks/use-location).
```jsx
const Confirm = () => {
  // Get current location's state
  const { state } = useLocation();
  
  // Display the data using `state.{input name}`
  // In this case, input name will be the value we set on input register from the Form component
  return (
    <div>
      <p>firstName: {state.firstName}</p>
      <p>lastName: {state.lastName}</p>
      <p>Gender: {state.gender}</p>
      <p>Country: {state.country}</p>
      <Link to="/" state={state}>
        <button>back</button>
      </Link>
      <Link to="/complete">
        <button>Submit</button>
      </Link>
    </div>
  );
};
```
Note that we passed the form data again on this line.
```jsx
...
      <Link to="/" state={state}>
        <button>back</button>
      </Link>
...
```
This is because when the user clicks the `back` button, we can "remember" the current input data and we would be able to display it to our form.

To do this, we will again get the form data values from the `locations` <u>state</u> prop and ww will display it as the defaultValues using `useForm`'s [<u>reset</u>](https://react-hook-form.com/api/useform/reset).
```jsx
const Form = () => {
  const navigate = useNavigate();
  const { state } = useLocation();
  const { register, reset, handleSubmit } = useForm();

  const onSubmit = handleSubmit((data) => {
    navigate("/confirm", { state: data });
  });

  useEffect(() => {
    // reset the entire form and set the defaultValues with state value
    reset(state);
  }, []);
...
```

We're done!

You can find the complete source in this [link](https://codesandbox.io/s/quizzical-gwen-wtqtdz).
****