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
register
input 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
useController
per component. If you need to use more than one, make sure you rename the prop. May want to consider usingController
instead.const { field: input } = useController({ name: 'test' }) const { field: checkbox } = useController({ name: 'test1' }) <input {...input} /> <input {...checkbox} />