React Hook Forms — Managing Forms Efficiently at Scale
Managing forms in React can easily become painful as your app scales. It could probably be due to the unorganised approach you followed while starting a project or writing the same boilerplate in every component or even sometimes applying hacks for tricky use cases. Speaking of the solutions, there are many form libraries out there and some of them handle forms really well but organising and keeping the code tidy is still up to you. In this article we’re going to solve this problem by building our form as simple as coding forms in vanilla HTML which can be used elegantly in any production app.
First list down some of the goals that we are trying to accomplish using react hook form.
- Cutting down the boilerplate — we should be able to render the forms with clean and DRY code
- Validations — Perform simple and complex validations easily
- Flexibility — we should be able to put input fields at any level nested inside the form
- Accessibility — At the very basic level, the form elements should be easily accessible via keyboard
- Self detected submit button state — the button should automatically enable/disable or show loader as per the form state
- Performance — Last but not the least, it is crucial one especially when rendering large number of fields inside the form.
To make things as clear as possible, we’ll make this simple code below render our form using React Hook Form, a performant and easy to plug-in library for React forms.
Set up React app
Let’s begin with setting up our react app by running npx create-react-app hooks-form && yarn add react-hook-form
Next, we will create our reusable form and input components to cut down all the boilerplate.
React Hook Form provides us useForm
and useFormContext
hooks to get the form context right away and within the nested components respectively. We’ll be using both of these hooks for the communication between the form and input components.
First we’ll create the Form
component followed by the input components such text fields, checkboxes, dropdown select, etc.
Build the Form component
We’ll initialise the form using useForm
hook, and pass on all the methods as props to the form via FormProvider
component. This will provide form state to the input components.
Build the form input elements
Now that we have our Form
component ready, we’ll create the form elements starting with the Input
component.
Input Component
Since we don’t know how deeply we would nest the input components, we’ll use useFormContext
to hook it up with its parent Form
component that we created before.
Checkbox Component
We’ll create the checkbox component the same way we did in the Input
component, just adding type checkbox
to it.
Select Component
This will be slightly different from the previous components as we’ll be using a 3rd party plugin for this. Keeping accessibility in mind, the best one I found is React Select.
You can install the plugin using yarn add react-select
and create the component as below:
Submit Button Component
The purpose of building the Button
component is to make it handle enabled/disabled/loading state itself. Here, we’re simply disabling the button until the form fields are dirty or when the form is being submitted.
Form Validation
Till now, we have made our form functional and able to submit form data.
As our next requirement, we need to add validations to our form elements. We’ll allow two types of validations: one is to simply check if a required field is filled or not and other by providing a pattern to validate the value.
As an example, the Input
component that we created before will now receive two extra props: required
and validation
.
The same way we can implement validation in our other components.
Summing up
In this article, we’ve created the components that are built on the basis of React Hooks with bare minimum code. If you wish to play around the code, here’s the Github’s link.