</> Controller: ControllerProps
React Hook Form embraces uncontrolled components and native inputs; however, it's hard to avoid working with external controlled components such as React-Select, AntD and MUI. This wrapper component makes it easier for you to work with them.
Note: if you simply want to control a field's value from outside the form, it's not necessary to use Controller. You can simply use the values option of useForm.
Props
The following table contains information about the arguments for Controller.
| Name | Type | Required | Description |
|---|---|---|---|
name | FieldPath | ✓ | Unique name of your input. |
control | Control | The control object is from invoking useForm. Optional when using FormProvider. | |
render | Function | This is a render prop. A function that returns a React element and provides the ability to attach events and value into the component. This simplifies integrating with external controlled components with non-standard prop names. Provides onChange, onBlur, name, ref and value to the child component, and also a fieldState object which contains specific input state. | |
rules | Object | Validation rules in the same format for register options, which includes:required, min, max, minLength, maxLength, pattern, validate | |
shouldUnregister | boolean = false` | Input will be unregistered after unmount and defaultValues will be removed as well. Note: this prop should be avoided when using with useFieldArray as unregister function gets called after input unmount/remount and reorder. | |
disabled | boolean = false` | disabled prop will be returned from field prop. Controlled input will be disabled and its value will be omitted from the submission data. | |
defaultValue | unknown | Important: Cannot apply undefined to defaultValue or defaultValues at useForm.
| |
exact | boolean = true | This prop will enable an exact match for input name subscriptions, default to true. |
Return
The following table contains information about properties which Controller produces.
| Object Name | Name | Type | Description |
|---|---|---|---|
field | onChange | (value: any) => void | A function which sends the input's value to the library. It should be assigned to the onChange prop of the input and the value should not be undefined. This prop updates formState and you should avoid manually invoking setValue or other APIs related to field updates. |
field | onBlur | () => void | A function which sends the input's onBlur event to the library. It should be assigned to the input's onBlur prop. |
field | value | unknown | The current value of the controlled component. |
field | disabled | boolean | The disabled state of the input. |
field | name | string | Input's name being registered. |
field | ref | React.ref | A ref used to connect hook form to the input. Assign ref to component's input ref to allow hook form to focus the error input. |
fieldState | invalid | boolean | Invalid state for current input. |
fieldState | isTouched | boolean | Touched state for current controlled input. |
fieldState | isDirty | boolean | Dirty state for current controlled input. |
fieldState | error | object | error for this specific input. |
formState | isDirty | boolean | Set to true after the user modifies any of the inputs.
|
formState | dirtyFields | object | An object with the user-modified fields. Make sure to provide all inputs' defaultValues via useForm, so the library can compare against the defaultValues
|
formState | touchedFields | object | An object containing all the inputs the user has interacted with. |
formState | defaultValues | object | The value that was set in useForm's defaultValues or updated defaultValues via the reset API. |
formState | isSubmitted | boolean | Set to true after the form has been submitted. Will remain true until the reset method is invoked. |
formState | isSubmitSuccessful | boolean | Indicates that the form was successfully submitted without any runtime error. |
formState | isSubmitting | boolean | true if the form is currently being submitted. false otherwise. |
formState | isLoading | boolean | true if the form is currently loading async default values.Important: this prop is only applicable to async defaultValues |
formState | submitCount | number | The number of times the form was submitted. |
formState | isValid | boolean | Set to true if the form doesn't have any errors.setError has no effect on isValid formState; isValid will always be derived from the entire form validation result. |
formState | isValidating | boolean | Set to true during validation. |
formState | errors | object | An object with field errors. There is also an ErrorMessage component to retrieve error messages easily. |
Examples:
Web
import ReactDatePicker from "react-datepicker"import { TextField } from "@material-ui/core"import { useForm, Controller } from "react-hook-form"type FormValues = {ReactDatepicker: string}function App() {const { handleSubmit, control } = useForm<FormValues>()return (<form onSubmit={handleSubmit((data) => console.log(data))}><Controllercontrol={control}name="ReactDatepicker"render={({ field: { onChange, onBlur, value, ref } }) => (<ReactDatePickeronChange={onChange} // send the value to hook formonBlur={onBlur} // notify when the input is touched or blurredselected={value}/>)}/><input type="submit" /></form>)}
React Native
import { Text, View, TextInput, Button, Alert } from "react-native"import { useForm, Controller } from "react-hook-form"export default function App() {const {control,handleSubmit,formState: { errors },} = useForm({defaultValues: {firstName: "",lastName: "",},})const onSubmit = (data) => console.log(data)return (<View><Controllercontrol={control}rules={{required: true,}}render={({ field: { onChange, onBlur, value } }) => (<TextInputplaceholder="First name"onBlur={onBlur}onChangeText={onChange}value={value}/>)}name="firstName"/>{errors.firstName && <Text>This is required.</Text>}<Controllercontrol={control}rules={{maxLength: 100,}}render={({ field: { onChange, onBlur, value } }) => (<TextInputplaceholder="Last name"onBlur={onBlur}onChangeText={onChange}value={value}/>)}name="lastName"/><Button title="Submit" onPress={handleSubmit(onSubmit)} /></View>)}
Video
The following video showcases what's inside Controller and how it was built.
-
It's important to be aware of each prop's responsibility when working with external controlled components such as MUI, AntD, and Chakra UI.
Controlleracts as a "spy" on your input by reporting and setting its value.- onChange: send data back to hook form
- onBlur: report that the input has been interacted with (focus and blur)
- value: set up the input's initial and updated value
- ref: allow the input to be focused when there is an error
- name: give the input a unique name The following CodeSandboxes demonstrate the usage:
- MUI and other components
- Chakra UI components
-
Do not
registerinput again. This component is made to take care of the registration process.<Controllername="test"render={({ field }) => {// return <input {...field} {...register('test')} />; ❌ double up the registrationreturn <input {...field} /> // ✅}}/> -
Customise what value gets sent to hook form by transforming the value during
onChange.<Controllername="test"render={({ field }) => {// sending integer instead of string.return (<input{...field}onChange={(e) => field.onChange(parseInt(e.target.value))}/>)}}/>
Thank you for your support
If you find React Hook Form to be useful in your project, please consider starring and supporting it.