如何在Formik分步表单中配置Yup验证?解决schema报错问题
Formik分步表单Yup验证Schema报错解决
用Formik构建分步表单时,尝试传入Yup Schema数组实现分步验证,出现报错:schema[(intermediate value)(intermediate value)(intermediate value)] is not a function
错误原因
Formik的validationSchema属性仅接受单个Yup对象或返回Yup对象的函数,直接传入数组会导致Formik尝试调用数组(而非函数)进行验证,从而抛出错误。
解决方案
方式一:根据当前步骤动态返回对应Schema
保留原有的Schema数组,将validationSchema改为动态返回当前步骤对应Schema的函数:
- 保留原Schema数组定义:
const schema = [ yup.object().shape({ field1: yup.string().required("cannot be empty"), field2: yup.string().required("cannot be empty"), }), yup.object().shape({ field3: yup.string().required("cannot be empty"), field4: yup.string().required("cannot be empty"), }), yup.object().shape({ field5: yup.string().required("cannot be empty"), field6: yup.string().required("cannot be empty"), }), ];
- 修改Formik组件的
validationSchema配置:
<Formik initialValues={initialValues} // 动态返回当前步骤对应的Schema validationSchema={() => schema[currentStep]} onSubmit={_handleSubmit} > {({ isSubmitting, dirty, isValid, values, resetForm, validateForm }) => ( <Form> {_renderStepperForm(currentStep)} <Button size="sm" disabled={currentStep === 0} onClick={goToPreviousStep} > Previous </Button> <Button type="submit" size="sm" onClick={async () => { // 手动触发当前步骤验证,通过后再跳转 const errors = await validateForm(); if (Object.keys(errors).length === 0) { goToNextStep(); } }} > {currentStep + 1 === stepConstant?.length ? "save" : "Next"} </Button> </Form> )} </Formik>
关键注意事项
currentStep需是Formik组件可访问的状态(比如用useState管理的变量)- 建议在跳转下一步前手动调用
validateForm(),确保当前步骤所有字段验证通过后再切换步骤,避免跳过验证 - 若需保留已完成步骤的验证状态(防止用户返回修改后跳过验证),可在切换步骤时重新验证对应步骤
方式二:合并Schema并通过条件控制验证规则(可选)
如果需要确保已完成步骤的字段始终有效,可将所有字段的验证规则合并到一个Schema中,通过yup.when根据当前步骤动态启用验证:
const schema = yup.object().shape({ field1: yup.string().when('currentStep', { is: (step) => step >= 0, then: () => yup.string().required("cannot be empty"), }), field2: yup.string().when('currentStep', { is: (step) => step >= 0, then: () => yup.string().required("cannot be empty"), }), field3: yup.string().when('currentStep', { is: (step) => step >= 1, then: () => yup.string().required("cannot be empty"), }), // 其他字段同理 });
此时需将currentStep传入Formik的initialValues或通过上下文传递,确保Yup能获取到步骤状态。
内容的提问来源于stack exchange,提问作者Olland Timisela
相关产品推荐
相关产品推荐

