register:
register method is no longer occurred at ref, instead invoke the function itself and spread the props into the input. The function itself will return the following props: onChange, onBlur, name and ref.
Important: input value and reference will no longer get removed after unmount unless shouldUnregister is true.
- <input ref={register({ required: true })} name="test" /> + <input {...register('test', { required: true })} />
You can use this codemod library to speed up the process: https://github.com/react-hook-form/codemod by running the following command:
npx @hookform/codemod v7/update-register
On top of that, for better type support, we have removed bracket syntax and replaced with dot syntax.
- test[2].test + test.2.test
Custom register
You will no longer need the name attribute for custom register, you can supply the name of the input straight way.
- register({ name: 'test' }) + register('test')
ValueAs
valueAs will be invoked before validate function.
- <input ref={register({ valueAsNumber: true, validate: (value) => parseInt(value) === 2 ) })} name="test" /> + <input {...register('test', { valueAsNumber: true, validate: (value) => value === 2 ) }} /> // no longer need to parse again
Missing ref
register works for any uncontrolled inputs , however, there are components which expose ref name differently.
const { ref, ...rest } = register('test') // invoke this before render <Input {...rest} inputRef={ref} />
Controller:
We made some change to align consistently with useController's API.
asprop has been removed, and we will consistently be usingrenderprop in v7.renderprop will return an object which containsfieldandfieldState.
- <Controller as={<input />} /> + <Controller render={({ field }) => <input {...field} />} - <Controller render={(props, meta) => <input {...props} />} /> + <Controller render={({ field, fieldState }) => <input {...field} />} />
ValueAs
The Controller component rules prop no longer supports setValueAs or valueAs* for useController. Do these value transformations in your controlled component.
reset:
In V7, we made some changes in our API to keep them more consistent and declarative. Reset's second option is the exact reason.
- reset(values, { isDirty: true }) + // second argument is still optional + reset(values, { + keepDefaultValues: true, // new + keepValues: true, // new + keepDirty: true, + })
errors:
errors object has been moved into formState object. This will info hook form that errors object is been subscribed.
You can use this codemod library to speed up the process: https://github.com/react-hook-form/codemod by running the following command:
npx @hookform/codemod v7/move-errors-to-formState
- const { errors } = useForm(); + const { formState: { errors } } = useForm();
watch:
watch an array of inputs will return array instead object
- const { test, test1 } = watch(['test', 'test1']); + const [test, test1] = watch(['test', 'test1']);
trigger:
Manually triggers form or input validation. This method is also useful when you have depedant validation as react hook form
- await trigger("test") // Returns true|false + await trigger("test") // Returns void
setError:
We have fixed the setError function to be consistent with the rest of the APIs.
- setError('test', { type: 'type', message: 'issue', shouldFocus: true }) + setError('test', { type: 'type', message: 'issue' }, { shouldFocus: true })
touched:
Renamed touched to touchedFields.
- const { touched } = formState; + const { touchedFields } = formState;
resolver:
We made some huge improvement on resolver, and the third argument now need to host more value than just a single boolean.
- resolver: (values: any, context?: object) => Promise<ResolverResult> | ResolverResult + resolver: ( + values: any, + context?: object, + options: { + criteriaMode?: 'firstError' | 'all', + names?: string[], + fields: { [name]: field } // Support nested field + } + ) => Promise<ResolverResult> | ResolverResult
useFieldArray:
We are offering better focus management in useFieldArray, so if you want to disable the focus behaviour, you will have to adjust the option as well.
- append({ test: 'test' }, false); + append({ test: 'test' }, { shouldFocus: false });
useFieldArray no longer need to supply with a generic, formValues type will inherited from useForm.
- useFieldArray<FieldArrayValues>(); + useFieldArray();
Input name will be strictly type checked with as const.
<input {...register(`test.${index}.firstName` as const)} />
useTypedController:
This component is getting deprecated, use useController instead.
- <TypedController - as="textarea" - name={['nested', 'object', 'test']} - defaultValue="" - rules={{ required: true }} - /> + <Controller + name={'nested.object.test'} + defaultValue="" + rules={{ required: true }} + render={({ field }) => <textarea {...field} />} + />);
Types:
We have made quite a few rename on the type for a better name and consistency. please refer to the TS page for the updated type names.
shouldUnregister:
In V7, the new default for the useFormoption: shouldUnregister is false. Previously it was defaulted to true.
Important: input value and reference will no longer get removed after unmount unless shouldUnregister is true.