Changelog
[7.54.0] - 2024-12-09
Changed
useForm return methods will be memorized based formState update
[7.53.0] - 2024-8-31
Added
- add support for
onBlur with formState isValid
Changed
validateFields will only trigger re-render for async validation
[7.51.0] - 2024-3-2
Added
- added 'validateFields' to formState
const {
formState: { validateFields },
} = useForm();
[7.49.0] - 2023-12-10
Added
- add reactive
errors prop at useForm
useForm({
errors,
});
[7.48.0] - 2023-11-05
Added
- added new
disabled prop for useForm to disable the entire form
const App = () => {
const [disabled, setDisabled] = useState(false);
const { handleSubmit } = useForm({ disabled });
return (
<form
onSubmit={handleSubmit(async () => {
setDisabled(true);
await sleep(100);
setDisabled(false);
})}
/ >
);
}
[7.47.0] - 2023-10-02
Added
reset api with keepIsSubmitSuccessful option, keep successfully submitted form state.
<Form
onSubmit={() => {
reset(formValues, {
keepIsSubmitSuccessful: true,
});
}}
/>
[7.46.0] - 2023-09-03
Added
const [disabled, setDisabled] = useState(false);
useController({
disabled,
});
- Trigger passed names to construct resolver options
- Add
exact option for array name in useWatch
Changed
- Update
isDirty when setting disabled in register
Fixed
- Prevent
reset argument mutation
[7.45.0] - 2023-06-20
Changed
- Controller with type check on
onChange
- onChange: (...event: any[]) => void;
+ onChange: (event: ChangeEvent | FieldPathValue<TFieldValues, TName>) => void;
- Include missing generic for
useFormContext
- export const useFormContext: <TFieldValues extends FieldValues, TransformedValues extends FieldValues | undefined = undefined>() => UseFormReturn<TFieldValues>;
+ export const useFormContext: <TFieldValues extends FieldValues, TContext = any, TransformedValues extends FieldValues | undefined = undefined>() => UseFormReturn<TFieldValues, TContext, TransformedValues>;
[7.44.0] - 2023-06-14
Added
// Send post request with formData
<Form
action="/api"
control={control}
onSuccess={() => {
alert("Great");
}}
/>
// Send post request with json form data
<Form action="/api" encType="application/json" headers={{ accessToken: 'test' }}>
{errors.root?.server.type === 500 && 'Error message'}
{errors.root?.server.type === 400 && 'Error message'}
</Form>
// Send post request with formData with fetch
<Form
onSubmit={async ({ formData, data, formDataJson, event }) => {
await fetch("api", {
method: "post",
body: formData,
});
}}
/>
- support
TransformedValues with useFormContext
useFormContext<FormValue, TransformedValues>()
- added
TTransformedValues to FormProvider
FormProviderProps<TFieldValues, TContext, TTransformedValues>
[7.43.0] - 2023-01-30
Added
- support global error type
const onSubmit = async () => {
setError('root.serverError', {
type: response.statusCode,
});
};
const onClick = () => {
setError('root.random', {
type: 'random',
});
};
return (
<>
{errors.root.serverError.type === 400 && <p>server response message</p>}
<p>{errors.root?.random?.message}</p>
</>
);
[7.42.0] - 2023-01-13
Added
- build in validation
validate support second argument for form values
export function validateNumber(_: number, formValus: FormValues) {
return formValus.number1 + formValus.number2 === 3;
}
<input
type="number"
{...register('number1', {
validate: validateNumber,
valueAsNumber: true,
})}
/>;
Changed
handleSubmit no longer catch onSubmit callback error
- Remove deprecated for
fieldState.invalid
[7.41.0] - 2022-12-17
Added
useForm added values props
const values = await fetch('API');
useForm({
values,
});
- new
isLoading formState for async defaultValues
const {
formState: { isLoading },
} = useForm();
Changed
useForm support async defaultValues props
const {
formState: { isLoading },
} = useForm({
defaultValues: fetch('API'),
});
[7.40.0] - 2022-11-30
Changed
- async validation (or combined with sync) will always the take the latest validation result and abort the previous
[7.39.5] - 2022-11-21
Changed
- Conditional render
useFormState will trigger an extra re-render to reflect the current formState
[7.39.0] - 2022-11-2
Changed
isValid formState is no longer only applicable with onChange, onTouched, and onBlur mode.
[7.38.0] - 2022-10-19
Added
- support build-in validation with input type week and time
<input {...register("week", { min: "2022-W40" })} type="week" />
<input {...register("time", { min: "11:00" })} type="time" />
[7.37.0] - 2022-10-07
Added
- new formState
defaultValues
const { formState, watch } = useForm({
defaultValues: { name: 'test' },
});
const { defaultValues } = useFormState();
const name = watch('name');
return (
<div>
<p>Your name was {defaultValues.name}</p>
<p>Updated name is {name}</p>
</div>
);
Changed
- defaultValues: complex object data contains prototype methods will not be cloned internally
[7.36.0] - 2022-9-20
Added
- reset to support callback syntax
reset((formValues) => {
return {
...formValues,
partialData: 'onlyChangeThis',
};
});
[7.35.0] - 2022-9-10
Added
- new type
FieldPathByValue field path by value generic implementation
function CustomFormComponent<
TFieldValues extends FieldValues,
Path extends FieldPathByValue<TFieldValues, Date>,
>({ control, name }: { control: Control<FieldValues>; name: Path }) {
const { field } = useController({
control,
name,
});
}
function App() {
const { control } = useForm<{
foo: Date;
baz: string;
}>();
return (
<form>
<CustomFormComponent control={control} name="foo" /> {/* no error */}
<CustomFormComponent control={control} name="baz" />{' '}
{/* throw an error since baz is string */}
</form>
);
}
Changed
- form context support children prop type
<FormProvider {...methods}>
<div /> // ✅
<div /> // ✅
</FormProvider>
[7.34.0] - 2022-7-28
Added
- Build in validation support for
useFieldArray with rules prop
useFieldArray({
name: 'test',
rules: {
required: true,
minLength: 2,
maxLength: 10,
validate: (fieldArrayValues) => {
if (fieldArrayValues[2].title === 'test') {
return 'validate Error';
}
},
},
});
errors?.test?.root?.message;
[7.33.0] - 2022-6-24
Breaking Change
@hookform/resolvers needs to upgraded to version ^2.9.3 above
useFormContext do always required to provide a generic type check for your form, without providing generic will now require developers to convert error messages to String to pass the type check
useFormContext<FormValues>();
const { formState } = useFormContext();
String(formState.errors?.input?.message);
Changed
- Deprecate
NestedValue and UnpackNestedValue type, will be removed in the next major version. Important: If you are using them, it may cause TS compile error, so please just remove the type usage.
type FormValues = {
- select: NestedValue<{
- nested: string
- }>
+ select: {
+ nested: string
+ }
}
type Data = UnpackNestedValue<FieldValues>
formState's errors is now mapped/merged with FieldError
UseFormHandleSubmit has removed unused function generic
[7.32.0] - 2022-6-10
Changed
UseFormRegisterReturn name type change from string to TFieldName
[7.31.0] - 2022-5-11
Added
- new:
reset optional prop: keepDirtyValues
reset(
{
firstName: 'bill',
lastName: 'luo',
},
{ keepDirtyValues: true },
);
Changed
useFieldArray auto-correct field array errors on user action
const { append } = useFieldArray();
append({ data: '' });
[7.30.0] - 2022-4-17
Changed
- improve checkboxes value determine by defaultValues
useForm({
defaultValues: {
checkboxes: [],
},
});
register('checkboxes');
[7.29.0] - 2022-3-30
Changed
- tsconfig config change from es2017 to es2018
[7.28.0] - 2022-3-13
Changed
register API options deps now support string
register('test', { deps: 'test' });
[7.27.0] - 2022-2-11
Added
- new option for
setFocus to select the entire field value
setFocus('fieldName', { shouldSelect: true });
[7.25.2] - 2022-1-29
Changed
onTouched mode will honor focusout event
[7.25.0] - 2022-1-22
Added
getFieldState get individual field state
export default function App() {
const {
register,
getFieldState,
formState: { isDirty, isValid },
} = useForm({
mode: 'onChange',
defaultValues: {
firstName: '',
},
});
const fieldState = getFieldState('firstName');
return (
<form>
<input {...register('firstName', { required: true })} />
<p>{getFieldState('firstName').isDirty && 'dirty'}</p>
<p>{getFieldState('firstName').isTouched && 'touched'}</p>
<button
type="button"
onClick={() => console.log(getFieldState('firstName'))}
>
field state
</button>
</form>
);
}
[7.24.0] - 2022-1-14
Changed
useController return prop: onChange, onBlur and ref will be memorized with useCallback
[7.23.0] - 2022-1-12
Changed
useFieldArray change keyName is no longer required when field value contains id
const App = () => {
const { control, register, handleSubmit } = useForm<FormValues>({
defaultValues: {
test: [{ id: 'UUID5678', test: 'data' }],
},
});
const { fields, append } = useFieldArray({
control,
name: 'test',
});
return (
<form>
{fields.map((field, index) => {
return <input key={field.id} {...register(`test.${index}.test`)} />;
})}
<button
type={'button'}
onClick={() => {
append({
id: 'UUID1234', // id value will be retained
test: '1234',
});
}}
>
append
</button>
</form>
);
};
useFormState will no longer fire state update after hook unmount
UseFormHandleSubmit type will infer formValues
[7.22.0] - 2021-12-14
Changed
- Browser native reset API will no longer be invoked when
reset provided with value
const onSubmit = (data) => {};
React.useEffect(() => {
if (formState.isSubmitSuccessful) {
reset({ something: '' });
}
}, [formState, reset]);
handleSubmit(onSubmit);
to
const onSubmit = (data) => {
setSubmittedData(data);
reset(data);
};
handleSubmit(onSubmit);
[7.21.0] - 2021-12-06
Changed
shouldUseNativeValidation will pass down validation props both at client and server render
const { register } = useForm()
<input {...register('name', { required: true })} />
<input name="name" required /> // both client and server render
[7.20.3] - 2021-11-26
Changed
- register
onChange will share same logic with useController for non standard event payload
const { onChange } = register('test');
onChange('stringIsValid'); // this is only valid use case for JS
- empty node in
formState will no longer gets unset
[7.20.0] - 2021-11-19
Added
- new
exact prop for useWatch
- new
exact prop for useFormState
useWatch({
name: 'test.test',
exact: true,
});
useFormState({
name: 'test.test',
exact: true,
});
Changed
useWatch subscription will occurred at useEffect instead before render
[7.19.0] - 2021-11-05
Added
const { resetField } = useForm();
resetField('test');
resetField('test', {
keepError: true,
keepDirty: true,
keepTouched: true,
defaultValue: 'test1',
});
Changed
useController will return shallow clone value for the following data type on each rerender
- object:
{... value}
- array:
[...value]
[7.18.1] - 2021-11-02
- revert
FieldPathWithValue
[7.18.0] - 2021-10-28
Added
- bring back
FieldPathWithValue
- schema errors parent object look up
const validationSchema = object().shape({
questions: array().min(1, 'Array cannot be empty'),
});
<button
type="button"
onClick={() => {
remove(questionIndex);
}}
>
Remove
</button>;
[7.17.0] - 2021-10-02
Added
- new type
FieldPathWithValue to improve generic components type support
type ExpectedType = { test: string };
const Generic = <FormValues extends FieldValues>({
name,
control,
}: {
name: FieldPathWithValue<FormValues, ExpectedType>;
control: Control<FormValues>;
}) => {
const {
field: { value, ...fieldProps },
} = useController<FormValues, ExpectedType>({
name,
control,
defaultValue: { test: 'value' },
});
return <input type="text" value={value.test} {...fieldProps} />;
};
[7.16.1] - 2021-09-27
Changed
formState subscription no longer subscribed at useEffect instead the execution of each hook
[7.16.0] - 2021-09-25
Added
register allowed pass custom onChange and onBlur
<input
type="text"
{...register('test', {
onChange: (e) => {},
onBlur: (e) => {},
})}
/>
[7.15.0] - 2021-09-05
Added
useFieldArray new method replace()
const { control } = useForm({
defaultValues: {
test: [{ value: 'lorem' }, { value: 'ipsum' }],
},
});
const { fields, replace } = useFieldArray({
control,
name: 'test',
});
const handleFullyReplacement = (): void => {
replace([{ value: 'dolor' }, { value: 'sit' }, { value: 'amet' }]);
};
- Improved to not map types defined with
interface.
import { useForm } from 'react-hook-form';
interface CustomValue {
custom: string;
}
type FormValues = {
fieldName: CustomValue;
};
const { formState: errors } = useForm<FormValues>({
defaultValues: { fieldName: { custom: 'value' } },
});
[7.14.0] - 2021-08-27
Added
register add dependent validation
const App = () => {
const { register, getValues } = useForm();
return (
<form>
<input
{...register('firstName', {
validate: (value) => {
return getValues('lastName') === value;
},
})}
/>
<input {...register('lastName', { deps: ['firstName'] })} /> // dependant
validation
</form>
);
};
[7.13.0] - 2021-08-22
Added
Trigger
- Trigger will enable object name trigger and field array name trigger
useFieldArray({ name: 'test' });
trigger('name');
register
- added a
disabled prop as an option to toggle input disable attribute
- register will be able to seek input DOM reference through the
ref callback
register('test', { disabled: true })
<div {...register('test')}>
<input name="test" /> // this input will be registered
</div>
useWatch
- added
disabled prop to toggle the state subscription.
useWatch({ disabled: true });
useFormState
- added
disabled prop to toggle the state subscription.
useFormState({ disabled: true });
setValue
- allow set value for non-registered inputs include nested object and array field.
<input {...register('test.0.firstName')} />
setValue('test', [{ firstName: 'bill' }, {firstName: 'kotaro}, {firstName: 'joris'}]) // this will works
[7.12.0] - 2021-07-24
Added
- new
useForm config delayError
useForm({
delayError: 500, // delay error appear with 500ms
});
[7.11.0] - 2021-07-13
Added
update method to update an field array inputs
const { update } = useFieldArray();
update(0, data);
[7.10.0] - 2021-07-02
Changed
defaultValue is no longer a required prop for register input with useFieldArray
[7.9.0] - 2021-06-19
Added
- new config at
useForm to enabled native browser validation
const { register, handleSubmit } = useForm({
shouldUseNativeValidation: true,
});
[7.8.5] - 2021-06-15
Change
useController no longer access input ref except focus event for focus management
[7.8.0] - 2021-06-5
Added
setValue support shouldTouch to update formState touchFields
setValue('firstName', 'value', { shouldTouch: true });
register now accept value as option
register('firstName', { value: 'value' });
Changed
isValid will initialise as false
[7.7.1] - 2021-05-30
Fixed
shouldUnregister: false should not shallow merge or register absent input fields from defaultValues
[7.7.0] - 2021-05-29
Added
trigger support focus with error input
trigger('inputName', { shouldFocus: true });
Changed
handleSubmit will throw error within the onSubmit callback
[7.6.0] - 2021-05-15
Changed
useForm will register missing inputs from defaultValues
const App = () => {
const { register, handleSubmit } = useForm({
defaultValues: {
test: { firstName: 'bill', lastName: 'luo' },
},
});
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('test.firstName')} />
<button />
</form>
);
};
[7.5.0] - 2021-05-09
Changed
isSubmitSuccessful will return false when handleSubmit callback failed with Error or Promise reject.
- unmounted input will no longer get validated even with
shouldUnregister: false
[7.4.0] - 2021-05-04
Added
- new
name prop for useFormState to subscribe to individual inputs.
useFormState({
name: 'inputName',
});
[7.2.2] - 2021-04-21
Changes
- set
shouldUnregister to true will not shallow merge defaultValues
[7.2.0] - 2021-04-19
Changes
shouldUnregister config to remove input value after unmount
useForm({
shouldUnregister: true
})
register('test', {
shouldUnregister: true
})
<Controller shouldUnregister={true} />
useController({ shouldUnregister: true })
useFieldArray({ shouldUnregister: true })
[7.0.6] - 2021-04-12
Changes
register will retrieve onChange's target value when component'ref is not a valid input element.
[7.0.0-rc.7] - 2021-03-28
Changes
- change type name from
RefCallbackHandler to UseFormRegisterReturn for register callback's return
[7.0.0-rc.7] - 2021-03-23
Changes
useFieldArray will produce an empty array [] when no field is presented.
[7.0.0-rc.1] - 2021-03-08
Changes
setValue with field array will register all inputs before rendering.
[7.0.0-beta.17] - 2021-03-03
Changes
append, prepend and insert will register deeply nested inputs at useFieldArray.
[7.0.0-beta.15] - 2021-02-27
Changes
- typescript array index restriction removed.
append, prepend and insert will register inputs during each action at useFieldArray.
[7.0.0-beta.11] - 2021-02-20
Changes
- change
ArrayKey type to number | '${number}'
[7.0.0-beta.10] - 2021-02-19
Changes
- Change
useController's meta into fieldState and include formState, these change will be applied to Controller too.
- const { field, meta } = useController({ control });
+ const { field, fieldState, formState } = useController({ control });
[7.0.0-beta.9] - 2021-02-19
Changes
- typescript array index support is changed to
49 instead of 99
[7.0.0-beta.4] - 2021-02-08
- Breaking change:
valueAs will be run before the built-in validation and resolver
- <input {...register('test', { validate: (data: string) => {}, valueAsNumber: true })} />
+ <input {...register('test', { validate: (data: number) => {}, valueAsNumber: true })} />
[7.0.0-beta.1] - 2021-02-08
Changes
useWatch will no longer required defaultValue for field Array
[7.0.0-beta.0] - 2021-02-06
Changes
- Breaking change: shallow merge defaultValues with result (#4074)
useForm({ defaultValues: { test: 'test' } });
getValues();
getValues();
[v7.0.0-alpha.2] - 2021-02-04
Changes
- Breaking change:
setError's shouldFocus option has been moved into the third argument.
- setError('test', { type: 'type', message: 'issue', shouldFocus: true })
+ setError('test', { type: 'type', message: 'issue' }, { shouldFocus: true })
- Breaking change: type name changes:
- UseFormMethods
+ UseFormReturn
- UseFormOptions
+ UseFormProps
- UseFieldArrayMethods
+ UseFieldArrayReturn
- UseFieldArrayOptions
+ UseFieldArrayProps
- UseControllerMethods
+ UseControllerReturn
- UseControllerOptions
+ UseControllerProps
- ArrayField
+ FieldArray
Fixes
- fix
setValue with Controller and reset with useFieldArray issues: 4111 & 4108 (#4113)
[v7.0.0-alpha.2] - 2021-02-02
Changes
- Breaking change:
setError's shouldFocus option has been moved to the third argument.
- setError('test', { type: 'type', message: 'issue', shouldFocus: true })
+ setError('test', { type: 'type', message: 'issue' }, { shouldFocus: true })
Fixes
- fix #4078 issue with watch + mode: onChange
Improvements
- remove internal deep clone (#4088)
- remove transformToNestObject (#4089)
[v7.0.0-alpha.1] - 2021-02-01
Changes
const { remove } = useFieldArray({ name: 'test' })
remove();
getValues();
getValues();
Improvements
- change internal field names into
Set (#4015)
- improve
onChange perf with `resolver (#4017)
- improve field array name look up perf (#4030)
[v7.0.0-alpha.0] - 2021-01-31
Added
- new custom hook
useFormState (#3740)
const { isDirty, errors } = useFormState();
watch support can subscribe to the entire form with a callback
watch((data, { name, type }) => {
console.log('formValue', data);
console.log('name', name);
console.log('type', type);
});
useController includes new isValidating state (#3778)
useController includes new error state (#3921)
const {
meta: { error, isValidating },
} = useController({ name: 'test' });
- new
unregister second argument (#3964)
unregister('test', { keepDirty: true });
- Resolver add
field being validated (#3881)
- 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 action can focus input by name and index
append(object, config: { shouldDirty: boolean, focusIndex: number, focusName: string })
insert(object, config: { shouldDirty: boolean, focusIndex: number, focusName: string })
prepend(object, config: { shouldDirty: boolean, focusIndex: number, focusName: string })
Changes
- <input ref={register, { required: true }} name="test" />
+ <input {...register('name', { required: true })} />
+ <TextInput {...register('name', { required: true })} />
- Breaking change:
name with array will only support dot syntax instead of brackets.
- test[2].test
+ test.2.test
- Breaking change: remove
as prop at Controller and fix render prop consistency (#3732)
- <Controller render={props => <input {...props} />} />
+ <Controller render={({ field }) => <input {...field} />} />
- Breaking change: remove
errors alias (#3737)
- const { errors } = useForm();
+ const { formState: { errors } } = useForm();
- Breaking change: improved
reset second argument (#3905)
- reset({}, { isDirty: true })
+ reset({}, { keepIsDirty: true })
- Breaking change: change
touched to touchedFields for consistency (#3923)
- const { formState: { touched } } = useForm();
+ const { formState: { touchedFields }} = useForm();
- Breaking change:
trigger will no longer return validation result.
- await trigger('test') // return true or false
+ trigger('test') // void
remove isSubmitting proxy (#4000)
input register will no longer be removed due to unmount, user will have to manually invoke unregister
Improvements
useWatch internal mechanism improvement (#3754)
Controller and useController apply useFormState internally and improve performance (#3778)
register type support for input name (#3738)
Controller and useCOntroller type support for input name (#3738)
useFieldArray internal logic and data structure improvement (#3858)
- improve
useFieldArray internal fields update with subscription (#3943)
- improve tests structure (#3916)
useWatch type improvement (#3931)
- improve type support for nested field array with
const (#3920)
- improve
useFieldArray internal type structure (#3986)
MutationObserver removed from useForm
[6.15.0] - 2021-02-02
Changed
- radio input default selection will return
null instead of empty string ''
valueAsNumber with empty input will return NaN instead of 0
[6.14.0] - 2020-12-31
Changed
setValue without shouldUnregister:false will no longer deep clone its value instead with shallow clone
Added
- new formState
isValidating, this will set to true during validation.
const {
formState: { isValidating },
} = useForm();
[6.12.0] - 2020-12-12
Changed
- When invoking
reset({ value }) value will be shallow clone value object which you have supplied instead of deepClone.
const defaultValues = { object: { deepNest: { file: new File() } } };
useForm({ defaultValues });
reset(defaultValues);
useForm({ deepNest: { file: new File() } });
reset({ deepNest: { file: new File() } });
Added
- New custom hook
useController: This custom hook is what powers Controller, and shares the same props and methods as Controller. It's useful to create reusable Controlled input, while Controller is the flexible option to drop into your page or form.
import React from 'react';
import { TextField } from '@material-ui/core';
import { useController } from 'react-hook-form';
function Input({ control, name }) {
const {
field: { ref, ...inputProps },
meta: { invalid, isTouched, isDirty },
} = useController({
name,
control,
rules: { required: true },
defaultValue: '',
});
return <TextField {...inputProps} inputRef={ref} />;
}
[6.12.0] - 2020-11-28
Changed
useWatch will retrieve the latest value from reset(data) instead of return defaultValue
useWatch({
name: 'test',
defaultValue: 'data', // this value will only show on the initial render
});
- TS: name changed from
ValidationRules to RegisterOptions due to valueAs functionality included as register function.
Added
register function with additional options to transform value
valueAsDate
valueAsNumber
setValueAs
register({
valueAsNumber: true,
});
register({
valueAsNumber: true,
});
register({
setValueAs: (value) => value,
});
Added
[6.11.0] - 2020-11-07
Changed
defaultValues is required to measure isDirty, keep a single source of truth to avoid multiple issues raised around isDirty
- when
watch with useFieldArray, fields object is no longer required as defaultValue
- watch('fieldArray', fields);
+ watch('fieldArray');
[6.10.0] - 2020-10-31
Added
Controller will have an extra ref props to improve DX in terms of focus management.
<Controller
name="test"
render={(props) => {
return (
<input
value={props.value}
onChange={props.onChange}
ref={props.ref}
/>
);
}}
/>
<Controller name="test" as={<input />} />
Changed
resolver with group error object will no longer need with trigger to show and clear error. This minor version made hook form look at parent error node to detect if there is any group error to show and hide.
const schema = z.object({
items: z.array(z.boolean()).refine((items) => items.some((item) => item)),
});
{
items.map((flag, index) => (
<input
type="checkbox"
defaultChecked={false}
ref={register}
name={`items.${index}`}
/>
));
}
[6.9.0] - 2020-10-3
Changed
- with shouldUnregister set to false, empty Field Array will default [] as submission result.
const { handleSubmit } = useForm({
shouldUnregister: false,
});
useFieldArray({
name: 'test',
});
handleSubmit((data) => {
});
[6.8.4] - 2020-09-22
Changed
- when input unmounts
touched and dirtyFields will no longer get removed from formState (shouldUnregister: true).
[6.8.0] - 2020-09-09
Added
- new formState
isSubmitSuccessful to indicate successful submission
setError now support focus on the actual input
`typescript jsx
setError('test', { message: 'This is required', shouldFocus: true });
### Changed
- with `shouldUnregister:false` `defaultValues` data will be part of the submission data
- with `shouldUnregister:false` conditional field is going to work with `useFieldArray`
- `setValue` now support `useFieldArray`
```diff
- setValue('test', 'data')
+ setValue('test', [{ test: '123' }]) // make it work for useFieldArray and target a field array key
- remove
exact config at clearErrors
- clearErrors('test', { exact: false })
+ clearErrors('test')
[6.7.0] - 2020-08-30
Added
clearError have second option argument for clear errors which are exact or key name
register('test.firstName', { required: true });
register('test.lastName', { required: true });
clearErrors('test', { exact: false });
clearErrors('test.firstName');
[6.6.0] - 2020-08-28
Changed
[6.5.0] - 2020-08-23
Changed
errors is also part of formState object
disabled input will not be part of the submission data by following the HTML standard
[6.4.0] - 2020-08-15
Added
Controller's render prop will pass down name prop
handleSubmit take a second callback for errors callback
- new mode
onTouched will only trigger validation after inputs are touched
Changed
register no longer compare ref difference with React Native
[6.3.2] - 2020-08-11
Changed
- IE 11 version will be required to install
@babel/runtime-corejs3 as dependency at your own project
[6.3.0] - 2020-08-8
Changed
defaultValue is become required for useFieldArray at each input
[6.2.0] - 2020-07-30
Changed
- revert
getValues will return default values before inputs registration
[6.1.0] - 2020-07-26
Changed
resolver supports both async and sync
getValues will return default values before inputs registration
[6.0.7] - 2020-07-17
Added
Changed
- error message will support array of messages for specific type
- export type ValidateResult = Message | boolean | undefined;
+ export type ValidateResult = Message | Message[] | boolean | undefined;
[6.0.3] - 2020-07-10
Changed
- Controller
onFocus works with React Native
- Controller stop producing
checked prop by boolean value
[6.0.2] - 2020-07-8
Added
- export
UseFormOptions, UseFieldArrayOptions, FieldError, Field and Mode type
[6.0.1] - 2020-07-3
Added
- export
ValidationRules type
[6.0.0] - 2020-07-1
Added
- config for
shouldUnregister which allow input to be persist even after unmount
useForm({
shouldUnregister: false,
});
- auto focus with useFieldArray
append({}, (autoFocus = true));
prepend({}, (autoFocus = true));
insert({}, (autoFocus = true));
import { useForm, NestedValue } from 'react-hook-form';
type FormValues = {
key1: string;
key2: number;
key3: NestedValue<{
key1: string;
key2: number;
}>;
key4: NestedValue<string[]>;
};
const { errors } = useForm<FormValues>();
errors?.key1?.message;
errors?.key2?.message;
errors?.key3?.message;
errors?.key4?.message;
useWatch (new) subscribe to registered inputs.
<input name="test" ref={register} />;
function IsolateReRender() {
const { state } = useWatch({
name: 'test',
control,
defaultValue: 'default',
});
return <div>{state}</div>;
}
getValues() support array of field names
`typescript jsx
getValues(['test', 'test1']); // { test: 'test', test1: 'test1' }
- `useForm({ mode: 'all' })` support all validation
### Changed
- rename `validationResolver` to `resolver`
- rename `validationContext` to `context`
- rename `validateCriteriaMode` to `criteriaMode`
- rename `triggerValidation` to `trigger`
- rename `clearError` to `clearErrors`
- rename `FormContext` to `FormProvider`
- rename `dirty` to `isDirty`
- `dirtyFields` change type from `Set` to `Object`
- Controller with render props API, and removed the following props:
- onChange
- onChangeName
- onBlur
- onBlurName
- valueName
```diff
-<Controller
- as={CustomInput}
- valueName="textValue"
- onChangeName="onTextChange"
- control={control}
- name="test"
-/>
+<Controller
+ render={({ onChange, onBlur, value }) => (
+ <CustomInput onTextChange={onChange} onBlur={onBlur} textValue={value} />
+ )}
+ control={control}
+ name="test"
+/>
setError will focus one error at a time and remove confusing set multiple errors, behavior change.
- setError will persist an error if it's not part of the form, which requires manual remove with clearError
- setError error will be removed by validation rules, rules always take over errors
- setError('test', 'test', 'test')
+ setError('test', { type: 'test', message: 'bill'})
setValue will focus on input at a time
setValue('test', 'value', { shouldValidate: false, shouldDirty: false })
Removed
- remove
validationSchema and embrace validation resolver
- remove
nest option for watch & getValues, so data return from both methods will be in FormValues shape.
-getValues({ nest: true }); // { test: { data: 'test' }}
-watch({ nest: true }); // { test: { data: 'test' }}
+getValues(); // { test: { data: 'test' }}
+watch(); // { test: { data: 'test' }}
[5.0.0] - 2020-03-07
Breaking Change
Controller: onChange will only evaluate payload as event like object. eg: react-select will no longer need the extra onChange method at Controller.
import { TextInput } from 'react-native';
-<Controller
- as={<TextInput style={{ borderWidth: 2, borderColor: 'black'}} />}
- name="text"
- control={args => ({
- value: args[0].nativeEvent.text,
- })}
- onChange={onChange}
-/>
+<Controller
+ as={<TextInput style={{ borderWidth: 2, borderColor: 'black'}} />}
+ name="text"
+ control={args => args[0].nativeEvent.text}
+ onChange={onChange}
+/>
[4.0.0] - 2019-12-24
Breaking changes
import { useForm } from 'react-hook-form';
- nested
errors object and better typescript support
type form = {
yourDetail: {
firstName: string;
};
};
errors?.yourDetail?.firstName;
- triggerValidation argument change from
Object, Object[] to String, String[]
triggerValidation('firstName');
triggerValidation(['firstName', 'lastName']);
- watch support
{ nest: boolean }
watch(); // { 'test.firstName': 'bill' }
watch({ nest: true }); // { test: { firstName: 'bill' } }
register('test', { required: true });
- setError` support nested object
setError('yourDetail.firstName', 'test');
errors.yourDetails.firstName;
handleSubmit no longer rerun array inputs contains undefined or null
Added
- move
RHFInput into the main repo and rename it to Controller
<Controller control={control} name="test" />
Removed
[3.0.0] - 2019-04-21
Added
React Hook Form return a new formState: Object which contain the following information
dirty: when user interactive any fields
touched: what are the fields have interacted
isSubmitted: whether the form have been triggered with submitting
const {
formState: { dirty, touched, isSubmitted },
} = useForm();
[2.0.0] - 2019-03-29
Added
- support
ref={register} instead of only ref={register()}