NestedValue
This type will be useful when the input itself return nested data object.
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, 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
This type will support users to write custom validation 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, errors } = useForm<FormValues>({ resolver }); const onSubmit = handleSubmit((data) => console.log(data)); return ( <form onSubmit={onSubmit}> <input name="firstName" placeholder="Kotaro" ref={register} /> {errors?.firstName && <p>{errors.firstName.message}</p>} <label>Last Name</label> <input name="lastName" placeholder="Sugawara" ref={register} /> <input type="submit" /> </form> ); }
SubmitHandler
This type is useful when submitted data is not matching with FormValues
type.
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 name="firstName" ref={register} /> <input name="lastName" ref={register} /> <input name="email" type="email" ref={register} /> <input type="submit" /> </form> ); }
Control
This type support custom hook such as useFieldArray
, useWatch
and future custom hooks in this library.
import React from "react"; import { useForm, useWatch, Control } from "react-hook-form"; type FormValues = { firstName: string; lastName: string; }; function IsolateReRender({ control }: { control: Control }) { const firstName = useWatch<FormValues["firstName"]>({ 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 ref={register} name="firstName" /> <input ref={register} name="lastName" /> <IsolateReRender control={control} /> <input type="submit" /> </form> ); }
UseFormMethods
This type is useful when you are using Context
's Consumer
instead ofuseFormContext
hook.
import React from "react"; import { useForm, UseFormMethods, 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: UseFormMethods<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 name="firstName" ref={register} /> <Input name="lastName" ref={register} /> <Select name="sex" ref={register} options={[ { label: "Female", value: "female" }, { label: "Male", value: "male" }, { label: "Other", value: "other" } ]} /> <Input type="submit" /> </> )} </Form> ); }
UseFormOptions
export type UseFormOptions< 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'; }>;
UseFieldArrayOptions
export type UseFieldArrayOptions< TKeyName extends string = 'id', TControl extends Control = Control > = { name: string; keyName?: TKeyName; control?: TControl; };
FieldError
export type FieldError = { type: string; ref?: Ref; types?: MultipleFieldErrors; message?: Message; };
Field
export type Field = { ref: Ref; mutationWatcher?: MutationWatcher; options?: RadioOrCheckboxOption[]; } & ValidationRules;
ArrayField
export type ArrayField< TFieldArrayValues extends FieldValues = FieldValues, TKeyName extends string = 'id' > = TFieldArrayValues & Record<TKeyName, string>;
Mode
export type Mode = { onBlur: 'onBlur'; onChange: 'onChange'; onSubmit: 'onSubmit'; all: 'all'; };
ValidationRules
export type ValidationRules = 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>; }>;