React.js中Formik结合Yup实现差异化错误展示求助
Formik + Yup 实现差异化错误展示
需求明确:email字段按校验顺序依次展示第一个错误,password字段要同时展示所有不满足的校验错误。
默认问题原因
Yup默认的链式校验是短路逻辑——只要某一条校验失败,就会停止后续校验并返回当前错误,所以你的password字段只会显示第一个不通过的规则错误,无法同时展示所有问题。而email的默认行为正好符合需求(只返回第一个错误),无需额外修改。
解决方案:自定义password的校验逻辑
通过Yup的.test()方法手动执行所有password校验规则,收集所有错误后统一返回,让Formik拿到完整的错误信息,再在渲染时拆分展示。
修改后的校验Schema
const validationPageTwo = Yup.object({ email: Yup.string().required("Required field"), password: Yup.string() .required("Required field password") .test('password-validation', '', function(value) { const errors = []; // 逐一检查所有密码规则,收集错误 if (!/(?=.{8,})/.test(value)) { errors.push("Must Contain 8 Characters"); } if (!/(?=.*[!@#\$%\^&\*])/.test(value)) { errors.push("One Special Case Character"); } if (!/(?=.*[0-9])/.test(value)) { errors.push("One Number"); } if (!/(?=.*[a-z])/.test(value)) { errors.push("One Lowercase"); } if (!/(?=.*[A-Z])/.test(value)) { errors.push("One Uppercase"); } // 有错误则返回包含所有错误的提示,无错误返回true if (errors.length > 0) { return this.createError({ message: errors.join(', ') }); } return true; }) }); const formik = useFormik({ initialValues: { name: "", surname: "", email: "", password: "", }, validationSchema: page === 1 ? validationPageOne : validationPageTwo, onSubmit: (values) => { if (page === 1) { setPage(2); } else { alert(JSON.stringify(values)); } }, });
渲染时拆分展示password错误
在表单的password输入框下方,把拼接的错误字符串拆分成列表展示:
{formik.errors.password && formik.touched.password && ( <div className="password-errors"> {formik.errors.password.split(', ').map((error, idx) => ( <p key={idx} className="error-text">{error}</p> ))} </div> )}
说明
- email字段保持原有链式校验,依然会按顺序返回第一个不满足的错误,符合需求。
- 通过
.test()方法绕开Yup的短路逻辑,手动遍历所有密码规则,收集所有错误后合并返回,再在渲染阶段拆分显示,实现同时展示所有password错误的效果。
内容的提问来源于stack exchange,提问作者Batuhan
相关产品推荐
相关产品推荐

