React Hook Form’s Controller: When and Why to Use It
When building forms in React, managing form state and validations can get tricky, especially when using third-party form components like Material-UI or Ant Design, which don’t integrate seamlessly with React Hook Form’s native inputs. This is where Controller comes into play—it provides a way to wrap external form components and still leverage React Hook Form’s powerful features like validation, state management, and error handling.
In this tutorial, we’ll explore what the Controller component does, why you need it, and how to use it effectively.
What is Controller
in React Hook Form?
Controller
is a component provided by React Hook Form that acts as a bridge between third-party form inputs (like Material-UI, Ant Design, or custom components) and React Hook Form's state management.
React Hook Form manages form inputs by default using its register
method. However, when you are working with controlled components—components where state is managed externally (e.g., Material-UI’s <TextField />
), using register
won’t work as expected. The Controller
component gives you control over those external inputs, allowing you to still use the same validation and state management features provided by React Hook Form.
When to Use Controller
You should use Controller
when:
Working with Controlled Components: Many third-party UI libraries use controlled components (where the component’s state is controlled by React), and React Hook Form’s
register
function only works out of the box with uncontrolled components.Controller
bridges this gap.Complex Form Components: If a form component has additional behavior or logic, such as a date picker or a custom select box, you’ll need
Controller
to properly integrate it into the form.Needing Dynamic Value Management: If your form input changes based on other fields or external factors,
Controller
gives you full control over the value and how it's updated.
Why Use Controller
?
Easy Integration with UI Libraries: Many UI libraries like Material-UI, Ant Design, or React Date Picker use controlled components.
Controller
allows you to integrate them into your form seamlessly.Centralized Validation: You can manage all your validation logic inside
Controller
, keeping your form logic consistent across controlled and uncontrolled components.Full Control: You can control the input's value, handle onChange events, and use React Hook Form's methods like validation and error handling, even with third-party components.
How to Use Controller
Let’s go through a step-by-step tutorial on how to use Controller
with Material-UI's <TextField />
component as an example.
1. Setting Up React Hook Form
First, install React Hook Form and Material-UI if you haven’t already.
npm install react-hook-form @mui/material @emotion/react @emotion/styled
Now import the necessary hooks and components into your project:
import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import { TextField, Button } from '@mui/material';
2. Creating a Simple Form
Create a basic form using React Hook Form’s useForm
hook and the Controller
component to wrap Material-UI’s <TextField />
.
const MyForm = () => {
const { handleSubmit, control, formState: { errors } } = useForm();
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* First Name Field with Controller */}
<Controller
name="firstName"
control={control}
defaultValue=""
rules={{ required: 'First name is required' }}
render={({ field }) => (
<TextField
{...field}
label="First Name"
variant="outlined"
error={!!errors.firstName}
helperText={errors.firstName ? errors.firstName.message : ''}
/>
)}
/>
{/* Submit Button */}
<Button type="submit" variant="contained" color="primary">
Submit
</Button>
</form>
);
};
3. Key Points Explained
name
: Thename
prop specifies the field name (in this case, "firstName") which is used by React Hook Form to track its value and validation state.control
: Thecontrol
prop is passed from theuseForm
hook and is required byController
to manage the form state.defaultValue
: This sets the initial value of the input field. For controlled components, you must provide adefaultValue
.rules
: Validation rules are defined here. In this example, the "firstName" field is required.render
: This prop is where you specify how the input should be rendered. Inside the render prop, we pass all the necessary field props ({...field}
) to the Material-UI<TextField />
, making it work seamlessly with React Hook Form.
4. Handling Validation Errors
React Hook Form provides a simple way to handle validation errors. In the above example, if the "firstName" field is empty when submitting the form, an error will be shown below the input using helperText
.
The error state is managed by errors.firstName
:
error={!!errors.firstName}
helperText={errors.firstName ? errors.firstName.message : ''}
This allows you to display the validation message right next to the input field, enhancing user experience.
Advanced Example with Multiple Controllers
Here’s an example where we integrate both a text input and a select dropdown using Controller
.
import { MenuItem, Select } from '@mui/material';
const MyAdvancedForm = () => {
const { handleSubmit, control } = useForm();
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* Text Input Field */}
<Controller
name="username"
control={control}
defaultValue=""
render={({ field }) => <TextField {...field} label="Username" />}
/>
{/* Select Dropdown */}
<Controller
name="role"
control={control}
defaultValue=""
render={({ field }) => (
<Select {...field} label="Role">
<MenuItem value="admin">Admin</MenuItem>
<MenuItem value="user">User</MenuItem>
</Select>
)}
/>
<Button type="submit">Submit</Button>
</form>
);
};
In this example, both the TextField and Select components are wrapped in Controller
, ensuring their state is properly managed by React Hook Form.
Why You Should Use Controller
Flexibility: With
Controller
, you gain complete control over the form inputs, allowing you to use third-party or custom components.Validation: You can define custom validation rules within the
Controller
, enabling consistent validation logic across your forms.Error Management: Easily manage error states and provide helpful feedback to users with error messages displayed alongside the inputs.
Simplicity: It simplifies the integration of complex components (like date pickers or sliders) while maintaining the power of React Hook Form’s validation and state management.
Conclusion
The Controller
component in React Hook Form is a crucial tool when working with controlled components or third-party UI libraries like Material-UI or Ant Design. It provides you with full control over form inputs, allowing for flexible and powerful form handling while maintaining a clean, declarative syntax.
Subscribe to my newsletter
Read articles from Frank Lam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by