如何用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> ); }
几个关键细节要注意
Yup.lazy()的妙用:它能让我们根据数组元素的索引或者元素自身的属性,动态选择对应的验证规则,完美适配这种每个元素结构都不一样的场景。when()实现条件校验:第二个元素的customerId校验依赖自身的value,用when()就能轻松实现“当某个条件满足时才触发校验”的逻辑,你可以根据实际需求调整判断条件。- Formik数组字段的命名规则:数组元素的字段必须用
[索引].字段名的格式,比如[0].bankId对应第一个元素的bankId,Formik才能正确绑定和校验。
内容的提问来源于stack exchange,提问作者Codeman
相关产品推荐
相关产品推荐

