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

如何用Yup验证含异构对象的Formik数组初始值?指定字段条件校验

用Yup验证结构各异的Formik数组初始值方案

我来帮你搞定这个异构数组的Yup验证问题!先理清楚你的核心需求:

  • 要校验数组第一个元素里的bankId字段
  • 数组第二个元素的customerId字段,校验规则得依赖该元素自身的value值(比如当value为true时才要求必填)

先拆解下你的初始值结构

先把你给的初始值数组整理得更清晰,方便我们对应规则:

[
  { 
    "bankId": 0, 
    "companyId": 0, 
    "accountName": "", 
    "companyName": "", 
    "name": "Enable Virtual Credit Card", 
    "value": "false", 
    "key": "VC_ENABLED" 
  },
  { 
    "promotionalImage": "um-0000002416.jpg", 
    "logoImage": "um-0000002416.jpg", 
    "address2": "Abanda, AL. 11111", 
    "address1": "41", 
    "customerId": "10002416", 
    "company": "ABC", 
    "value": "", 
    "key": "UNITE" 
  },
  { 
    "name": "Invoice", 
    "accountReceivableEmail": "", 
    "value": "false", 
    "key": "INVOICE", 
    "accountPayableEmail": "" 
  }
]

编写Yup验证Schema

因为数组里每个元素结构不一样,咱们用Yup.array().of()搭配Yup.lazy()来动态生成每个元素的验证规则,这玩意儿对异构数组特别好用。

直接上代码,注释我都写清楚了:

import * as Yup from 'yup';

const validationSchema = Yup.array().of(
  Yup.lazy((item, index) => {
    // 处理数组第一个元素:校验bankId
    if (index === 0) {
      return Yup.object().shape({
        bankId: Yup.number()
          .integer('银行ID必须是整数')
          .min(1, '银行ID不能为0')
          .required('银行ID是必填项'),
        // 要是这个元素还有其他字段要校验,直接在这里加规则就行
      });
    }
    // 处理数组第二个元素:customerId校验依赖自身的value值
    else if (index === 1) {
      return Yup.object().shape({
        customerId: Yup.string().when('value', {
          // 这里判断条件:当value为true(不管是字符串还是布尔值)时触发必填校验
          is: (val) => val === 'true' || val === true,
          then: Yup.string()
            .required('UNITE配置开启时,客户ID不能为空')
            .matches(/^[0-9]+$/, '客户ID必须是纯数字'),
          // 没开启的时候,customerId可以为空
          otherwise: Yup.string().nullable(),
        }),
        // 其他字段的校验规则按需添加
      });
    }
    // 第三个及以后的元素:如果不需要校验,返回空的object schema就行
    else {
      return Yup.object().shape({});
    }
  })
);

在Formik里用上这个Schema

把上面写的validationSchema传给Formik组件的validationSchema属性就ok了,下面是个简单的使用示例:

import { Formik, Form, Field } from 'formik';

// 你的初始值数组
const initialValues = [ /* 这里放你给的初始值数组 */ ];

function ConfigForm() {
  return (
    <Formik
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={(values) => {
        console.log('提交的表单值:', values);
        // 这里写你的提交逻辑
      }}
    >
      {({ errors, touched }) => (
        <Form>
          {/* 渲染第一个元素的bankId字段 */}
          <div className="form-group">
            <label>银行ID</label>
            <Field name="[0].bankId" type="number" />
            {/* 显示错误提示 */}
            {errors[0]?.bankId && touched[0]?.bankId && (
              <span className="error-text">{errors[0].bankId}</span>
            )}
          </div>

          {/* 渲染第二个元素的开关和customerId */}
          <div className="form-group">
            <label>开启UNITE配置</label>
            <Field name="[1].value" type="checkbox" />
          </div>
          <div className="form-group">
            <label>客户ID</label>
            <Field name="[1].customerId" />
            {errors[1]?.customerId && touched[1]?.customerId && (
              <span className="error-text">{errors[1].customerId}</span>
            )}
          </div>

          {/* 其他元素的字段渲染按需添加 */}
          <button type="submit">提交配置</button>
        </Form>
      )}
    </Formik>
  );
}

几个关键细节要注意

  1. Yup.lazy()的妙用:它能让我们根据数组元素的索引或者元素自身的属性,动态选择对应的验证规则,完美适配这种每个元素结构都不一样的场景。
  2. when()实现条件校验:第二个元素的customerId校验依赖自身的value,用when()就能轻松实现“当某个条件满足时才触发校验”的逻辑,你可以根据实际需求调整判断条件。
  3. Formik数组字段的命名规则:数组元素的字段必须用[索引].字段名的格式,比如[0].bankId对应第一个元素的bankId,Formik才能正确绑定和校验。

内容的提问来源于stack exchange,提问作者Codeman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 07:13:11