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({
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()}