NestedValue
import React from 'react'; import { useForm, NestedValue } from 'react-hook-form'; import { Autocomplete, TextField, Select } from '@material-ui/core'; import { Autocomplete } from '@material-ui/lab'; type Option = { label: string; value: string; }; const options = [ { label: 'Chocolate', value: 'chocolate' }, { label: 'Strawberry', value: 'strawberry' }, { label: 'Vanilla', value: 'vanilla' }, ]; export default function App() { const { register, handleSubmit, watch, setValue, formState: { errors } } = useForm<{ autocomplete: NestedValue<Option[]>; select: NestedValue<number[]>; }>({ defaultValues: { autocomplete: [], select: [] }, }); const onSubmit = handleSubmit((data) => console.log(data)); React.useEffect(() => { register('autocomplete', { validate: (value) => value.length || 'This is required.', }); register('select', { validate: (value) => value.length || 'This is required.', }); }, [register]); return ( <form onSubmit={onSubmit}> <Autocomplete options={options} getOptionLabel={(option: Option) => option.label} onChange={(e, options) => setValue('autocomplete', options)} renderInput={(params) => ( <TextField {...params} error={Boolean(errors?.autocomplete)} helperText={errors?.autocomplete?.message} /> )} /> <Select value="" onChange={(e) => setValue('muiSelect', e.target.value as number[])}> <MenuItem value={10}>Ten</MenuItem> <MenuItem value={20}>Twenty</MenuItem> </Select> <input type="submit" /> </form> ); }
Resolver
import React from 'react'; import { useForm, Resolver } from 'react-hook-form'; type FormValues = { firstName: string; lastName: string; }; const resolver: Resolver<FormValues> = async (values) => { return { values: values.firstName ? values : {}, errors: !values.firstName ? { firstName: { type: 'required', message: 'This is required.', }, } : {}, }; }; export default function App() { const { register, handleSubmit, formState: { errors } } = useForm<FormValues>({ resolver }); const onSubmit = handleSubmit((data) => console.log(data)); return ( <form onSubmit={onSubmit}> <input {...register("firstName")} placeholder="Bill" /> {errors?.firstName && <p>{errors.firstName.message}</p>} <input {...register("lastName")} placeholder="Luo" /> <input type="submit" /> </form> ); }
SubmitHandler
import React from "react"; import { useForm, SubmitHandler } from "react-hook-form"; type FormValues = { firstName: string; lastName: string; email: string; }; export default function App() { const { register, handleSubmit } = useForm<FormValues>(); const onSubmit: SubmitHandler<FormValues> = data => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register("firstName")} /> <input {...register("lastName")} /> <input type="email" {...register("email")} /> <input type="submit" /> </form> ); }
Control
import React from "react"; import { useForm, useWatch, Control } from "react-hook-form"; type FormValues = { firstName: string; lastName: string; }; function IsolateReRender({ control }: { control: Control<FormValues> }) { const firstName = useWatch({ control, name: "firstName", defaultValue: "default" }); return <div>{firstName}</div>; } export default function App() { const { register, control, handleSubmit } = useForm<FormValues>(); const onSubmit = handleSubmit((data) => console.log(data)); return ( <form onSubmit={onSubmit}> <input {...register("firstName")} /> <input {...register("lastName")} /> <IsolateReRender control={control} /> <input type="submit" /> </form> ); }
UseFormReturn
import React from "react"; import { useForm, UseFormReturn, SubmitHandler } from "react-hook-form"; type InputProps = React.DetailedHTMLProps< React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement >; const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => ( <input ref={ref} {...props} /> )); type Option = { label: React.ReactNode; value: string | number | string[]; }; type SelectProps = React.DetailedHTMLProps< React.SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement > & { options: Option[] }; const Select = React.forwardRef<HTMLSelectElement, SelectProps>( ({ options, ...props }, ref) => ( <select ref={ref} {...props}> {options.map(({ label, value }) => ( <option value={value}>{label}</option> ))} </select> ) ); type FormProps<TFormValues> = { onSubmit: SubmitHandler<TFormValues>; children: (methods: UseFormReturn<TFormValues>) => React.ReactNode; }; const Form = <TFormValues extends Record<string, any> = Record<string, any>>({ onSubmit, children }: FormProps<TFormValues>) => { const methods = useForm<TFormValues>(); return ( <form onSubmit={methods.handleSubmit(onSubmit)}>{children(methods)}</form> ); }; type FormValues = { firstName: string; lastName: string; sex: string; }; export default function App() { const onSubmit = (data: FormValues) => console.log(data); return ( <Form<FormValues> onSubmit={onSubmit}> {({ register }) => ( <> <Input {...register("firstName")} /> <Input {...register("lastName")} /> <Select {...register("sex")} options={[ { label: "Female", value: "female" }, { label: "Male", value: "male" }, { label: "Other", value: "other" } ]} /> <Input type="submit" /> </> )} </Form> ); }
UseFormProps
export type UseFormProps< TFieldValues extends FieldValues = FieldValues, TContext extends object = object > = Partial<{ mode: Mode; reValidateMode: Mode; defaultValues: UnpackNestedValue<DeepPartial<TFieldValues>>; resolver: Resolver<TFieldValues, TContext>; context: TContext; shouldFocusError: boolean; shouldUnregister: boolean; criteriaMode: 'firstError' | 'all'; }>;
UseFieldArrayReturn
export type UseFieldArrayReturn< TFieldArrayValues extends FieldValues = FieldValues, TKeyName extends string = 'id' > = { swap: (indexA: number, indexB: number) => void; move: (indexA: number, indexB: number) => void; prepend: ( value: Partial<TFieldArrayValues> | Partial<TFieldArrayValues>[], shouldFocus?: boolean, ) => void; append: ( value: Partial<TFieldArrayValues> | Partial<TFieldArrayValues>[], shouldFocus?: boolean, ) => void; remove: (index?: number | number[]) => void; insert: ( index: number, value: Partial<TFieldArrayValues> | Partial<TFieldArrayValues>[], shouldFocus?: boolean, ) => void; fields: Partial<ArrayField<TFieldArrayValues, TKeyName>>[]; };
UseFieldArrayProps
export type UseFieldArrayProps< TKeyName extends string = 'id', TControl extends Control = Control > = { name: string; keyName?: TKeyName; control?: TControl; };
UseControllerReturn
export type UseControllerReturn< TFieldValues extends FieldValues = FieldValues > = { field: ControllerRenderProps<TFieldValues>; fieldState: InputState; };
UseControllerProps
export type UseControllerProps< TFieldValues extends FieldValues = FieldValues > = { name: FieldName<TFieldValues>; rules?: Exclude<RegisterOptions, 'valueAsNumber' | 'valueAsDate' | 'setValueAs' >; onFocus?: () => void; defaultValue?: unknown; control?: Control<TFieldValues>; };
FieldError
export type FieldError = { type: string; ref?: Ref; types?: MultipleFieldErrors; message?: Message; };
FieldErrors
export type FieldErrors< TFieldValues extends FieldValues = FieldValues > = DeepMap<TFieldValues, FieldError>;
Field
export type Field = { ref: Ref; mutationWatcher?: MutationWatcher; options?: RadioOrCheckboxOption[]; } & RegisterOptions;
FieldPath
This type is useful when you define custom component's name
prop.
export type FieldPath<TFieldValues extends FieldValues> = Path<TFieldValues>;
FieldValues
export type FieldValues = Record<string, any>;
FieldArrayWithId
export export type FieldArrayWithId< TFieldValues extends FieldValues = FieldValues, TFieldArrayName extends FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>, TKeyName extends string = 'id', > = FieldArray<TFieldValues, TFieldArrayName> & Record<TKeyName, string>;
Mode
export type Mode = { onBlur: 'onBlur'; onChange: 'onChange'; onSubmit: 'onSubmit'; all: 'all'; };
RegisterOptions
export type RegisterOptions = Partial<{ required: Message | ValidationRule<boolean>; min: ValidationRule<number | string>; max: ValidationRule<number | string>; maxLength: ValidationRule<number | string>; minLength: ValidationRule<number | string>; pattern: ValidationRule<RegExp>; validate: Validate | Record<string, Validate>; }>;
FormStateProxy
export type FormStateProxy<TFieldValues extends FieldValues = FieldValues> = { isDirty: boolean; dirtyFields: Dirtied<TFieldValues>; isSubmitted: boolean; submitCount: number; touched: FieldNames<TFieldValues>; isSubmitting: boolean; isValid: boolean; errors: FieldErrors<TFieldValues>; };