如何从 formik 形式的 DOM 中删除空错误 div?

How to remove empty error div from DOM in formik form?

我在身份验证页面中有以下代码来控制警报消息:

<div className="messages-wrapper">
  {formik.errors.email &&
    <div className="alert alert-danger">
      <ErrorMessage name="email" />
    </div>
  }
  {formik.errors.password &&
    <div className="alert alert-danger">
      <ErrorMessage name="password" />
    </div>
  }
  {error && <div className="alert alert-danger">{error}</div>}
</div>

我意识到有时 DOM 它有:

<div class="alert alert-danger"></div>

因此,显示粉红色条

有谁知道如何实现只有在有文本时才显示警告栏?

确保初始化所有input/field值(可能是您忘记初始化电子邮件的值?

我已尝试重现您的问题,但当我未初始化任何字段值时,我看到了空白的粉红色条。

  ...
<Formik
      initialValues={{ email: "", password: "" }} // <---- correct - both email and password are initialised
      // initialValues={{ password: "" }} // <--- wrong, email is not initialised. With this, there will be empty pink bar issue
      validate={validate}
      onSubmit={(values, actions) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
        }, 1000);
      }}
  ...

有用的话见this example我在codesandbox中创建的

最后,我不知道为什么你有这行代码{error && <div className="alert alert-danger">{error}</div>}。也请检查一下。 祝你好运。

您看到粉红色条的原因是当您提交表单时出现错误时会呈现错误消息。

由于您在警报消息中使用 bootstrap classes,例如 alert alert-danger,因此警报的样式为 bootstrap(假设您使用的是 bootstrap)

根据bootstrap documentation

Use the .alert-${link} utility class to quickly provide matching colored links within any alert.

And accordingly

alert-success - leaves a green color background
alert-info - shows a blue color background
alert-waning- shows a yellow color background
alert-danger - shows a pink/red color background

为了让您删除粉红色样式,您只需从警告消息中删除alert-dangerclass

{error && <div className="alert">{error}</div>}

现在这将继承 alert class 的样式,如果您不想要它,您可以添加您的自定义 class 并在其上应用样式

你的代码可能看起来像

<div className="messages-wrapper">
      {formik.errors.email && <div className="alert">
        <ErrorMessage name="email" />
      </div>
      }
      {formik.errors.password && <div className="alert">
        <ErrorMessage name="password" />
      </div>
      }
      {error && <div className="alert">{error}</div>}
    </div>

您提供的代码示例不足以为您提供明确的答案。

但据我所见,我可以推测出这么多:

  1. As per documentation 1 and 2 and the source code <ErrorMessage name="email"> 将 returns 一个字符串,你的代码大致相当于
    {formik.errors.email && <div className="alert alert-danger">
      {formik.touched.email && formik.errors.email ? formik.errors.email : null}
    </div>}
    
  2. 现在我看到出现空错误栏的两种可能性:

    1. formik.errors.email 必须是真实的,但不可打印(例如 " ")。
    2. formik.errors.email必须为真,formik.touched.email必须为假。

    很可能这是您遇到的第二个问题。

所以,如果我猜对了,您需要:

  1. 按照文档中的建议使用 ErrorMessage。像这样:
    <ErrorMessage name="email">
      {msg => <div className="alert alert-danger">{msg}</div>}
    </ErrorMessage>
    
    或者像这样:
    <ErrorMessage
      name="email"
      render={msg => <div className="alert alert-danger">{msg}</div>}
    />
    
  2. 或删除 <ErrorMessage>,但为 touched 添加一个检查
    {formik.touched.email && formik.errors.email &&
      <div className="alert alert-danger">{formik.errors.email}</div>
    }
    

不深入,我会简单地通过应用 css:

来修复
.alert:empty {
  display: none;
}

否则,我会在检查前trim值。例如

{formik.errors.email.trim() &&

您需要做的就是利用 touched 属性 of FormikState:

export interface FormikState<Values> {
    values: Values;
    errors: FormikErrors<Values>;
    touched: FormikTouched<Values>;   // <=== This one
    isSubmitting: boolean;
    isValidating: boolean;
    status?: any;
    submitCount: number;
}

以下是如何访问表单的 touched 状态:

<Formik
  initialValues={{ email: '', password: '' } as IForm}
  validate={(values) => {
    const errors = {} as IForm
    if (!values.email) {
      errors.email = 'Email Required'
    }
    return errors
  }}
  onSubmit={(values, { setSubmitting }) => {
    // ... submit handler
  }}
>
  {({ values, errors, touched, handleChange, handleBlur, handleSubmit, 
isSubmitting }) => (
                //  above ^ one
    <form onSubmit={handleSubmit}>
    // ... ...

然后在显示错误的时候使用(注意touched.emailtouched.password的用法):

<div className="messages-wrapper">
  {errors.email && touched.email && (
    <div className="alert alert-danger">
      <ErrorMessage name="email" />
    </div>
  )}

  {errors.password && touched.password && (
    <div className="alert alert-danger">
      <ErrorMessage name="password" />
    </div>
  )}
</div>

查看所有(问题+解决方案)的实际操作:Playground


快照:DOM 内部包装器中没有空 div