react-hook-form:为何getValues无法返回实时最新值?
问题
我有一组单选按钮A、B、C,希望仅当选中B时,其下方的选择框为必填项。以下是简化代码:
interface ButtonFormType { notificationType: "A" | "B" | "C"; selectedId?: string; } const { register, handleSubmit, getValues, watch, formState: { errors }, } = useForm<ButtonFormType>(); // ...省略中间代码 return( <form onSubmit={submit}> <RadioGroup defaultValue={getValues("buttonType")}> <VStack> <Radio {...register("buttonType")} value={"A"}> Button A </Radio> <Radio {...register("buttonType")} value={"B"}> Button B </Radio> <FormControl isInvalid={!!errors[`selectedId`]}> <Select placeholder={"select"} {...register("selectedId", { required: getValues("buttonType") === "B" ? "please select id" : false, })} > {idList.map(({ id, title }) => { return ( <option key={id} value={id}> {title} </option> ); })} </Select> </FormControl> <Radio {...register("buttonType")} value={"C"}> Button C </Radio> </VStack> </RadioGroup> <HStack marginY="40px" spacing={4}> <Button type="submit"> Submit </Button> </HStack> </form> )
当选中B但未选择下拉框内容并点击提交按钮时,第一次不会触发错误提示;再次点击提交才会出现错误。排查发现getValues("buttonType")不会随单选按钮切换实时更新,仅在提交后才更新。替换为watch后问题解决,但不理解getValues失效的原因,求解答。
原因分析
getValues的特性:getValues是同步函数,只会获取组件初始渲染或上一次表单提交后的表单值快照,不会主动监听字段实时变化。切换单选按钮时,它返回的还是旧值,导致第一次提交时校验逻辑用的是切换前的buttonType,无法触发必填校验。watch的特性:watch是专门监听表单字段变化的API,返回响应式值。当buttonType变化时,会触发组件重新渲染,校验逻辑能拿到最新值,确保规则实时生效。- 校验规则的执行时机:
register里的校验规则用getValues时,只会在组件初始化时计算一次,后续字段变化不会重新计算规则;而watch返回的响应式变量会在字段变化时重新触发规则判断,因此能正确实现“选中B时下拉框必填”的逻辑。
内容的提问来源于stack exchange,提问作者amu03
相关产品推荐
相关产品推荐

