You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TypeScript项目:加载Modal时禁用Formik验证求助

解决Formik模态框打开即显示验证错误的问题

问题根源

  1. Add按钮类型错误:设置为type="submit",点击时直接触发Formik表单提交,执行验证逻辑
  2. Formik配置拼写错误:validateOnsubmit应为validateOnSubmit,导致配置不生效
  3. Field的onBlur绑定错误:直接执行函数(setRoleFieldState(values.role_category)),组件挂载时立即触发状态更新,间接触发验证
  4. 错误提示时机未控制:初始空值触发的验证错误未结合touched/submit状态判断,直接显示

分步解决方案

1. 修正Add按钮类型

将Add按钮改为type="button",仅负责打开模态框,不触发表单提交:

<Button
  size="s"
  class="primary"
  name="Add"
  type="button" {/* 修改此处 */}
  disabled={false}
  onClick={() => {
    setId(undefined);
    setFieldValue("role_category", "");
    setFieldValue("description", "");
    toggleModal();
  }}
></Button>

2. 修正Formik配置

确保属性名正确,仅在提交时触发验证:

<Formik
  initialValues={initialValues}
  validationSchema={validationSchema}
  onSubmit={handleSubmit}
  validateOnMount={false}
  validateOnSubmit={true} {/* 正确拼写 */}
  validateOnChange={false}
  validateOnBlur={false}
>

3. 修复Field的onBlur绑定

改为箭头函数延迟执行,避免组件挂载时触发:

<Field
  name="role_category"
  type="text"
  className="form-control"
  onBlur={() => setRoleFieldState(values.role_category)} {/* 修改为箭头函数 */}
/>
<Field
  name="description"
  type="text"
  className="form-control"
  onBlur={() => setDescriptionFieldState(values.description)} {/* 修改为箭头函数 */}
/>

4. 控制错误提示显示时机

结合Formik的touched状态和submitCount,仅当字段被触碰或表单提交过才显示错误:

{({ setFieldValue, values, touched, submitCount }) => (
  <Form>
    {/* ...其他代码... */}
    <div className="form-group">
      <label htmlFor="role_category">Role Category</label>
      <Field
        name="role_category"
        type="text"
        className="form-control"
        onBlur={() => setRoleFieldState(values.role_category)}
      />
      {(touched.role_category || submitCount > 0) && (
        <ErrorMessage
          name="role_category"
          component="div"
          className="alert yup-error"
        />
      )}
    </div>
    <div className="form-group">
      <label htmlFor="description">Description</label>
      <Field
        name="description"
        type="text"
        className="form-control"
        onBlur={() => setDescriptionFieldState(values.description)}
      />
      {(touched.description || submitCount > 0) && (
        <ErrorMessage
          name="description"
          component="div"
          className="alert yup-error"
        />
      )}
    </div>
    {/* ...其他代码... */}
  </Form>
)}

5. 复用Formik提交机制

移除Save按钮的自定义onClick,让Formik处理提交流程,确保验证通过后才执行保存:

<Button
  size="s"
  class="primary"
  name="Save"
  type="submit"
  disabled={roleFieldState === "" || descriptionFieldState === ""}
></Button>

在handleSubmit中处理保存逻辑:

const handleSubmit = async (values: typeof initialValues, { resetForm }) => {
  const roleValue = {
    role: values.role_category,
    des: values.description,
  };
  await handleSave(roleValue);
  toggleModal();
  resetForm(); // 可选:重置表单状态
};

6. 打开模态框时重置状态(可选)

确保每次打开模态框时表单状态干净,重置touched和submitCount:

// 先从Formik解构出resetForm
{({ setFieldValue, values, touched, submitCount, resetForm }) => (
  // ...
  <Button
    // ...
    onClick={() => {
      setId(undefined);
      resetForm({
        values: initialValues,
        touched: {},
        submitCount: 0,
      });
      toggleModal();
    }}
  ></Button>
)}

额外优化建议

  • 移除自定义的roleFieldState和descriptionFieldState,直接使用Formik的values和touched状态,减少冗余
  • 利用Formik的handleBlur自动维护touched状态:
<Field
  name="role_category"
  type="text"
  className="form-control"
  onBlur={(e) => {
    handleBlur(e); // 更新Formik的touched状态
    // 保留自定义逻辑(如果需要)
  }}
/>

内容的提问来源于stack exchange,提问作者Edi-nano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:01:01