Yup 表单验证中如何动态设置必填字段?
我在用 React Hook Form 配合 Yup 做表单验证,现在有个需求:当用户勾选“需要发票”时,发票抬头字段才变成必填。但我发现即使 Yup 的 schema 动态变了,表单也不会重新校验这个字段,已经填过的值不会触发错误,没填的也不报错,这是为啥?
我试过用 useEffect 重新生成 schema 并传给 useForm 的 resolver,但好像没生效。代码大概这样:
const schema = yup.object({
needInvoice: yup.boolean(),
invoiceTitle: yup.string().when('needInvoice', {
is: true,
then: (schema) => schema.required('发票抬头不能为空'),
otherwise: (schema) => schema.optional(),
}),
});
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: yupResolver(schema),
});
.when()本身是响应式的,不需要你重新创建 schema。真正的问题是 RHF 不会在依赖字段(needInvoice)变化时自动触发被依赖字段(invoiceTitle)的重新验证。解决方案很简单,在 needInvoice 变化时手动触发验证就行:
或者用 watch 监听:
这样当用户勾选需要发票时,就会立刻校验发票抬头字段,没填的话就会报错。
另外提醒一下,你的
otherwise用.optional()是对的,但有些版本可能需要写成.notRequired(),看具体用的 Yup 版本。