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 | string | ✓ | Unique name of your input. |
control | Object | control object provided by invoking useForm. Optional when using FormProvider. | |
defaultValue | any | The same as an uncontrolled component's defaultValue. When passing a boolean value, it will be treated as checkbox input. For more details, see useForm's defaultValues section.
| |
rules | Object | Validation rules in the same format as for Important: doesn't support
| |
shouldUnregister | boolean = false | Input will be unregistered after unmount and defaultValues will be removed as well. |
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. It should be assigned to the |
onBlur | () => void | A function which sends the input's onBlur event to the library. It should be assigned to the input's | |
value | unknown | The current value of the controlled component. | |
name | |||
Input's name being registered. | |||
ref | |||
A ref used to connect hook form to the input. Assign | |||
fieldState | invalid | boolean | Invalid state for current input. |
isTouched | boolean | Touched state for current controlled input. | |
isDirty | boolean | Dirty state for current controlled input. | |
error | object | error for this specific input. | |
formState | isSubmitSuccessful | boolean | Indicates whether the form was successfully submitted. |
isDirty | boolean | Set to | |
isSubmitted | boolean | Set to | |
dirtyFields | object | An object with the user-modified fields. Make sure to provide all inputs' defaultValues via useForm, so the library can compare the input value against the | |
touchedFields | object | An object containing all the inputs the user has interacted with. | |
isSubmitting | boolean |
| |
submitCount | number | Number of times the form was submitted. | |
isValid | boolean | Set to | |
isValidating | boolean | Set to |
import React from "react"; import { TextField } from "@material-ui/core"; import { useController, useForm } from "react-hook-form"; function Input({ control, name }) { const { field: { ref, ...inputProps }, fieldState: { invalid, isTouched, isDirty }, formState: { touchedFields, dirtyFields } } = useController({ name, control, rules: { required: true }, defaultValue: "", }); return <TextField {...inputProps} inputRef={ref} />; } function App() { const { control } = useForm(); return <Input name="firstName" control={control} />; }import * as React from "react"; import { useForm, useController, UseControllerProps } from "react-hook-form"; type FormValues = { FirstName: string; }; function Input(props: UseControllerProps<FormValues>) { const { field, fieldState } = useController(props); return ( <div> <input {...field} placeholder={props.name} /> <p>{fieldState.isTouched && "Touched"}</p> <p>{fieldState.isDirty && "Dirty"}</p> <p>{fieldState.invalid ? "invalid" : "valid"}</p> </div> ); } export default function App() { const { handleSubmit, control } = useForm<FormValues>({ defaultValues: { FirstName: "" }, mode: "onChange" }); const onSubmit = (data: FormValues) => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <Input control={control} name="FirstName" rules={{ required: true }} /> <input type="submit" /> </form> ); }
Tips
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 registrationIt'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 usingControllerinstead.const { field: input } = useController({ name: 'test' }) const { field: checkbox } = useController({ name: 'test1' }) <input {...input} /> <input {...checkbox} />