useController:
(props?: UseControllerProps) => { field: object, fieldState: object, formState: object }
This custom hook powers Controller. Additionally, it shares the same props and methods as Controller. It's useful for creating reusable Controlled input.
Props
The following table contains information about the arguments for useController.
| Name | Type | Required | Description | 
|---|---|---|---|
| name | FieldPath | ✓ | Unique name of your input. | 
| control | Control | controlobject provided by invokinguseForm. Optional when usingFormProvider. | |
| rules | Object | Validation rules in the same format for  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  | |
| disabled | boolean = false | 
 | |
| defaultValue | unknown | Important: Can not apply  
 | 
Return
The following table contains information about properties which useController produces.
| Object Name | Name | Type | Description | 
|---|---|---|---|
| field | onChange | (value: any) => void | A function which sends the input's value to the library. | 
| field | onBlur | () => void | A function which sends the input's onBlur event to the library. It should be assigned to the input's  | 
| 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  | 
| 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  
 | 
| 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  
 | 
| formState | touchedFields | object | An object containing all the inputs the user has interacted with. | 
| formState | defaultValues | object | The value which has been set at useForm's defaultValues or updated defaultValues via reset API. | 
| formState | isSubmitted | boolean | Set to trueafter the form is submitted. Will remaintrueuntil theresetmethod is invoked. | 
| formState | isSubmitSuccessful | boolean | Indicate the form was successfully submitted without any runtime error. | 
| formState | isSubmitting | boolean | trueif the form is currently being submitted.falseotherwise. | 
| formState | isLoading | boolean | 
 Important: this prop is only applicable to async  
 | 
| formState | submitCount | number | Number of times the form was submitted. | 
| formState | isValid | boolean | Set to  trueif the form doesn't have any errors.
 | 
| formState | isValidating | boolean | Set to trueduring validation. | 
| formState | validatingFields | object | Capture fields which are getting async validation. | 
| formState | errors | object | An object with field errors. There is also an ErrorMessage component to retrieve error message easily. | 
| formState | disabled | boolean | Set to trueif the form is disabled via thedisabledprop in useForm. | 
Examples
import { TextField } from "@material-ui/core";import { useController, useForm } from "react-hook-form";function Input({ control, name }) {const {field,fieldState: { invalid, isTouched, isDirty },formState: { touchedFields, dirtyFields }} = useController({name,control,rules: { required: true },});return (<TextFieldonChange={field.onChange} // send value to hook formonBlur={field.onBlur} // notify when input is touched/blurvalue={field.value} // input valuename={field.name} // send down the input nameinputRef={field.ref} // send input ref, so we can focus on input when error appear/>);}
Tips
- It's important to be aware of each prop's responsibility when working with external controlled components, such as MUI, AntD, Chakra UI. Its job is to spy on the input, report, and set its value. - onChange: send data back to hook form 
- onBlur: report input has been interacted (focus and blur) 
- value: set up input initial and updated value 
- ref: allow input to be focused with error 
- name: give input an unique name 
 - It's fine to host your state and combined with - useController.const { field } = useController();const [value, setValue] = useState(field.value);onChange={(event) => {field.onChange(parseInt(event.target.value)) // data send back to hook formsetValue(event.target.value) // UI state}}
- Do not - registerinput again. This custom hook is designed to take care of the registration process.const { field } = useController({ name: 'test' })<input {...field} /> // ✅<input {...field} {...register('test')} /> // ❌ double up the registration
- It's ideal to use a single - useControllerper component. If you need to use more than one, make sure you rename the prop. May want to consider using- Controllerinstead.const { field: input } = useController({ name: 'test' })const { field: checkbox } = useController({ name: 'test1' })<input {...input} /><input {...checkbox} />
Thank you for your support
If you find React Hook Form to be useful in your project, please consider to star and support it.