In this tutorial, I'll be showing you how to create a multi-page form – consisting of a Form page, Confirm / Review page, and Complete page only using react-router and react-hook-form.
1. First, let's create our pages/components.
// 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;
// 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;
// Complete
const Complete = () => {
return (
<div>
<p>Registration successful!</p>
</div>
);
};
export default Complete;
2. Next, by using react-hook-form's useForm
we will get the form data from our Form component.
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
state prop.
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
.
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.
...
<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
state prop and ww will display it as the defaultValues using useForm
's reset.
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.
Top comments (0)