You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 02:03:18