React Hook Form使用指南
表单作为用户交互中常见的形式,值的校验/收集/管理是个问题。
在react技术栈下中React Hook Form
包名: react-hook-form
功能强大,是个不错的方案。灵活恰当的使用它,可以提升code效率/可维护性。这里就把hook form的常用场景/使用/容易忽略的点/核心原理做一个总结,如有疏漏,请斧正。
当前版本:v7.56.3
,压缩使用的包体积为11KB左右
。
使用🔨
内置方法
实际使用中,我们常用的只是useForm/Controller/getValues
抛开常用的useForm/useWatch/Controller,hook-form还有其他一些方法,这里就介绍下。
useForm中的mode
mode不同,影响表单收集错误的时机,但是本身对于formState,比如isValid,又比如单个字段下的 validate,是并不影响的,都是会实时更新。
mode缺省值是onSubmit
useFormContext
hook
,很多时候,我们管理form是使用的useForm,如果表单组件是嵌套的,那么嵌套的表单项的值管理就成了问题。常常需要将父组件的control传递给子组件,然后子组件再传递给孙组件,这样一层一层传递,非常麻烦。如果是使用useFormContext,那么就可以直接在组件内部管理form的值,而不需要一层一层传递。
useFieldArray
hook
,有时数据存在数组/List类型。比如动态添加项,使用useFieldArray会更为方便。
const { fields, append, prepend, remove, swap, move, insert } = useFieldArray(
{
control, // control props comes from useForm (optional: if you are using FormProvider)
name: 'test' // unique name for your Field Array
}
);
watch
watchfunc
,useWatch用来监听关心的字段变化,或者所有字段当前的值,但假如想知道每次变化哪个字段,或者批量watch用于逻辑处理的话,可以使用watch方法。
const allFieldWatch = useWatch({
control,
name:['price'], // 如果name不传,则是watch所有字段
})
useEffect(() => {
const wFn = watch((data, {name}) => {
console.log('column changed', data, name) // data为修改后最新值
});
return wFn.unsubscribe;
}, [])
registers
registerfunc
,注册一个表单字段,返回对象,该方法主要是面向原生表单元素的,如果是非原生表单元素,比如Tea组件下的Input组件,注意onChange等方法是否会有问题。
<input
{...register('address', {
validate: (s) => {
console.log('address validate', s);
}
})}
/>
register vs Controller
如上所说,register适合原生,Controller适合高阶表单组件,如第三方。
resetfunc
/ setValue
reset方法如果没有声明字段值,则会重置为defaultValues设置的值。
reset();
reset操作是面向所有字段进行重置,并非部分字段。比如reset只标注了A字段,那么其它字段则会是undefined.
如果想reset单个字段,应该使用setValue法或者reset时候携带所有字段值
reset({ ...getValues(), price: 111 })
valueAsNumber/valueAsDate
<input
{...register('quantity', {
// valueAsNumber: true,
})}
/>
// "quantity": "2121212121"
// "quantity": 2121212121
如果是Controller方式,需要自行实现,比如field.onChange(Number(value))
官方推荐-实践
transform/parse
react-hook-form介绍的transform和parse只是个实践,并不是内置的功能。
配套-yup等校验类库
const schema = yup
.object()
.shape({
price: yup.number().required(),
quantity: yup.number().min(1).max(100).required(),
})
.required();
const formProps = useForm({
...,
resolver: yupResolver(schema),
});
注意:触发娇艳的实际还是取决于mode的设置。
dirty
常见问题❓
array数据更新,没有watch到
源码👀
包依赖
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18 || ^19"
},
延伸下。微信小程序开发框架taro是使用的react进行开发,那么如果需要表单校验的话,可以使用react-hook-form吗?
答案:No
补充信息
react-hook-form什么时候推出的
查询发现,react-hook-form于Mar 3, 2019发布的第一个版本,目前也属于高频维护。
其它form方案选择

useWatch原理
本身是在hook的effect中调用了form.control的subscribe方法,来监听表单值的变化,一旦值变动了,则会更新value对象。
export function useWatch<TFieldValues extends FieldValues>(
props?: UseWatchProps<TFieldValues>,
) {
...
React.useEffect(
() =>
control._subscribe({
name: _name.current as InternalFieldName,
...
callback: (formState) =>
!disabled &&
updateValue(
generateWatchOutput(
_name.current as InternalFieldName | InternalFieldName[],
control._names,
formState.values || control._formValues,
false,
_defaultValue.current,
),
),
}),
[control, disabled, exact],
);
const [value, updateValue] = React.useState(
control._getWatch(
name as InternalFieldName,
defaultValue as DeepPartialSkipArrayKey<TFieldValues>,
),
);
...
return value;
}