如何在Formik中向Yup校验传递Context?mode值获取失败
问题:Formik + Yup实现分模式(添加/编辑)的表单校验
背景
表单存在adding和editing两种模式:
- 添加模式下仅展示2个字段,无需校验额外3个字段
- 编辑模式下展示5个字段,额外的3个字段为必填项
需要通过Context控制不同模式下的校验逻辑,但尝试多种方案后未找到适配方式。
当前代码与问题
Formik组件的validate配置
<Formik {...} validate={(values: FormValues) => { try { validateYupSchema(values, getVersionsSchema, true, { mode: "testing" }); } catch (e) { return yupToFormErrors(e); } return {}; }} >
validateYupSchema参数定义
values: T, schema: any, sync?: boolean, context?: any
尝试的Yup校验方案(存在问题)
尝试用Yup的when方法监听context中的mode,但打印mode值为undefined:
export const getVersionsSchema = (t: TFunction<Namespace<"en">>) => Yup.object().shape({ {...} optIn: Yup.string().when("mode", (mode, schema) => { console.log(mode, schema); return schema.required("test"); }), {...} });
解决方向与修正代码
问题根源
Yup的when("mode")默认从表单values对象中读取字段值,但我们的mode是传入的context参数,并非values的一部分,因此无法获取到值。
方案1:使用Yup的test方法直接访问context
通过test方法的回调函数,从this.options.context中获取传入的mode参数,自定义校验逻辑:
export const getVersionsSchema = (t) => Yup.object().shape({ // 其他字段定义... optIn: Yup.string().test( "required-in-edit-mode", t("required"), function(value) { // 从context中读取当前模式 const { mode } = this.options.context || {}; // 编辑模式下校验必填,添加模式下跳过 return mode === "editing" ? !!value : true; } ), // 其他需分模式校验的字段同理... });
方案2:使用Yup.ref引用context中的属性
通过Yup.ref("$mode")直接引用context中的mode参数,结合when方法实现条件校验:
export const getVersionsSchema = (t) => Yup.object().shape({ // 其他字段定义... optIn: Yup.string().when( Yup.ref("$mode"), // 用$前缀标识context中的属性 (mode, schema) => { return mode === "editing" ? schema.required(t("required")) : schema; } ), // 其他需分模式校验的字段同理... });
注意事项
调用validateYupSchema时,需确保传入的context包含当前表单模式(比如从组件props或状态中获取真实的adding/editing值):
// 示例:假设当前模式从props中获取 <Formik {...} validate={(values) => { try { validateYupSchema(values, getVersionsSchema(t), true, { mode: props.formMode // 传入真实的模式值:"adding"或"editing" }); } catch (e) { return yupToFormErrors(e); } return {}; }} >
内容的提问来源于stack exchange,提问作者Daniel V.
相关产品推荐
相关产品推荐

