Formik+Yup校验Schema在MUI多步骤Dialog中异常求助
解决Formik多步骤表单全局触发校验的问题
问题根源
你直接将Yup Schema数组传给Formik的validationSchema属性,但Formik不支持数组类型的校验规则。它无法识别按步骤拆分的Schema,会默认对所有字段执行校验,导致当前步骤未输入的字段全部触发错误提示。
解决方案
1. 动态返回当前步骤的Schema
将validationSchema改为函数形式,根据当前步骤currentStep返回对应的Yup Schema,让Formik只校验当前步骤的字段。
2. 控制校验时机(可选)
如果不需要实时校验输入框,可关闭validateOnChange和validateOnBlur,只在点击「Next/Submit」时执行校验,避免输入过程中触发无关错误。
修正后的代码
Formik组件修改
<Formik innerRef={formikFormRef} enableReinitialize initialValues={businessTypeInitialState} // 动态返回当前步骤的校验Schema validationSchema={() => businessContactsSchema[currentStep]} // 可选:关闭实时校验,仅提交时校验 validateOnChange={false} validateOnBlur={false} onSubmit={(values, { resetForm }) => { // 原有提交逻辑保持不变 if (isLastStep) { let payload = { ...values, record_type_id: contactRecordType === 'Corporate' ? '1' : '2', contact_id: props.openDialog?.data?.contactId, same_address: isSameAddress, billingAddressId: props.openDialog?.data?.billingAddress.addressId, contactAddressId: props.openDialog?.data?.contactAddress.addressId, }; if (props.openDialog?.dialogType === 'addContact') { addContactMutation(payload, { onSuccess: (data) => { if (data.statusCode === 200) { queryClient.invalidateQueries('contacts'); setContactData(data); setCurrentStep(5); resetForm(); } else if (data.statusCode === 403) setAPIResponse({ message: data.message, code: data.statusCode }); else setAPIResponse({ message: 'There was a server error', code: data.statusCode }); }, }); } else if (props.openDialog?.dialogType === 'editContact') { updateContactMutation(payload, { onSuccess: (data) => { if (data.statusCode === 200) { queryClient.invalidateQueries('contactDetails'); setCurrentStep(0); props.onClose(); } }, }); } } else { if (isSameAddress && currentStep === 2) return setCurrentStep(currentStep + 2); return setCurrentStep(currentStep + 1); } }} > {/* 原有渲染逻辑保持不变 */} </Formik>
自定义实时校验(可选)
如果需要保留实时校验,但仅校验当前步骤字段,可替换validationSchema为自定义validate函数:
validate={(values) => { const errors = {}; const currentSchema = businessContactsSchema[currentStep]; try { // 校验当前步骤字段,abortEarly设为false收集所有错误 currentSchema.validateSync(values, { abortEarly: false }); } catch (err) { err.inner.forEach((e) => { errors[e.path] = e.message; }); } return errors; }}
额外说明
- 确保
enableReinitialize为true,切换步骤时Formik会重新计算校验规则 - Yup Schema数组
businessContactsSchema无需修改,保持原有结构即可
内容的提问来源于stack exchange,提问作者Puzant Bakjejian
相关产品推荐
相关产品推荐

