React Hook Form中解构isValid触发异常验证的原理探究
React Hook Form中解构useFormState的isValid引发验证行为变化的原因
我在React Hook Form库中发现一个有趣的现象:
- 当解构
useFormState返回的isValid属性时(即便完全不调用或使用它),输入框每一次按键都会触发字段的validate方法; - 但如果不解构
isValid,只解构errors这类属性,验证仅在输入框失焦(blur)时触发,符合配置的mode: "onBlur"预期。
背后的原理:Proxy对象
这个“魔法”行为的核心是Proxy对象。React Hook Form的useFormState返回的是一个被Proxy包装的状态对象:
- 当你解构
isValid时,会触发Proxy的get拦截陷阱。isValid代表整个表单的验证状态,要计算它的值,必须实时校验所有字段的合法性,因此会主动调用字段的validate方法; - 每次输入按键会触发组件重新渲染,此时解构
isValid的操作会重复触发上述的Proxy拦截与全局验证逻辑,导致validate方法被重复调用; - 而仅解构
errors时,errors是针对单个字段的错误信息,不需要触发全局的实时验证计算,因此验证行为保持配置的onBlur时机,仅在失焦时触发。
示例代码
import React from "react"; import ReactDOM from "react-dom"; import { Controller, FormProvider, useForm, useFormState } from "react-hook-form"; import "./styles.css"; const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const Input = () => { // 解开这行注释,输入框每次按键都会触发validate // const { isValid } = useFormState(); const { errors } = useFormState(); return ( <> <label htmlFor="username">用户名</label> <Controller defaultValue="" name="username" rules={{ validate: async (value) => { console.log("为什么解构isValid后会打印这条日志?"); await sleep(1000); return value === "bill"; } }} render={({ field }) => ( <input onChange={field.onChange} onBlur={field.onBlur} value={field.value} name="username" placeholder="请输入bill" /> )} /> <input type="submit" /> </> ); }; function App() { const methods = useForm({ mode: "onBlur", reValidateMode: "onChange" }); return ( <FormProvider {...methods}> <form onSubmit={console.log}> <Input /> </form> </FormProvider> ); }
内容的提问来源于stack exchange,提问作者Sheppard25
相关产品推荐
相关产品推荐

