Formik搭配react-bootstrap、yup表单校验未操作字段误报错问题咨询
问题解决方法
这个问题的根本原因是Formik默认会在任意字段触发onChange值变更时,对整个表单的所有字段执行全量校验,所以你修改第一个字段时,第二个未操作的必填空字段也会触发校验规则,提前展示错误提示。
你可以任选以下三种方案解决:
方案1:修改全局校验触发时机(改动最小)
关闭Formik默认的「值变更时全量校验」配置,仅保留字段失焦(用户点击过该字段再离开,视为已操作)时才校验对应字段,初始化Formik时修改配置即可:
<Formik initialValues={{ 你的表单项初始值 }} validationSchema={你的yup校验规则} validateOnChange={false} // 关闭值变更时的全量校验 validateOnBlur={true} // 仅在字段失焦时校验该字段 onSubmit={提交逻辑} >
方案2:错误提示增加touched状态判断(灵活性最高)
Formik会自动维护每个字段的touched状态,只有用户触发过该字段的onBlur事件后,对应字段的touched值才会变为true,你只需要在渲染错误提示的逻辑中增加这个判断即可,无需修改全局校验配置:
原错误提示代码示例:
{errors.xxx && <div className="text-danger">{errors.xxx}</div>}
修改后:
{errors.xxx && touched.xxx && <div className="text-danger">{errors.xxx}</div>}
这个方案可以保留全量校验的逻辑,同时保证未被用户操作过的字段即使校验不通过也不会展示错误提示。
方案3:自定义校验逻辑,仅校验已操作字段
如果有特殊的校验规则需求,你可以自定义Formik的validate函数,只对已经被用户操作过的字段执行校验,配合Yup使用的代码示例如下:
<Formik initialValues={{ 你的表单项初始值 }} validate={async (values, { touched }) => { // 过滤出所有已被用户触碰过的字段 const touchedFields = Object.fromEntries( Object.entries(values).filter(([key]) => touched[key]) ); try { // 仅校验已触碰字段 await schema.validate(touchedFields, { abortEarly: false }); return {}; } catch (err) { return err.inner.reduce((errors, item) => { errors[item.path] = item.message; return errors; }, {}); } }} onSubmit={提交逻辑} >
内容的提问来源于stack exchange,提问作者Greg-A
相关产品推荐
相关产品推荐

