在 Formik 中使用 ErrorMessage 组件显示 setFieldErrors 的值

Displaying Value of setFieldErrors Using ErrorMessage Component in Formik

请参阅下面的更新

我有一个使用 Formik 构建的登录表单组件,它与 Firebase 身份验证同步。我已将其设置为可以使用 setFieldError 道具显示来自 Firebase 的错误。以下是代码的相关部分:

export const LoginForm = () => {
  async function authenticateUser(values, setFieldError) {
    const { email, password } = values

    try {
      await firebase.login(email, password)
      navigate('/', { replace: true })
    } catch (error) {
      console.log('Authentication Error: ', error)
      await setFieldError('firebaseErrorMessage', error.message)
    }
  }

  return (
    <>
      <h1>Form</h1>
      <Formik
        render={props => <RenderForm {...props} />}
        initialValues={initialValues}
        validationSchema={validationSchema}
        onSubmit={async (
          values,
          { setFieldError, setSubmitting, resetForm }
        ) => {
          setSubmitting(true)
          authenticateUser(values, setFieldError)
          setSubmitting(false)
          resetForm()
        }}
      />
    </>
  )
}

const RenderForm = ({ errors, isSubmitting, isValid }) => (
  <Form>
    <h3>Sign Up</h3>
    <Email name="email" />
    <Password name="password" />
    <Button disabled={!isValid || isSubmitting} type="submit">
      Submit
    </Button>
    {errors.firebaseErrorMessage && <p>{errors.firebaseErrorMessage}</p>}
  </Form>
)

现在,这工作得很好。但是,如果我尝试使用 Formik 的 ErrorMessage 组件显示错误消息,则该消息不会显示。

换句话说,这个有效:

{errors.firebaseErrorMessage && <p>{errors.firebaseErrorMessage}</p>}

有效:

<ErrorMessage name="firebaseErrorMessage" />

知道为什么这不起作用以及如何让它起作用吗?

谢谢。

更新

这是我的初始值:

const initialValues = {
  email: '',
  password: '',
}

我认为您不应该将 Formik 的错误用于您的 Firebase 错误。 Formik 的错误用于验证表单输入。

要存储和引用 API 错误,您可以使用 Formik 的 status 对象。处理 API 错误是他为 status.

给出的示例

我认为问题在于,在 Formik 中,name 是指输入的名称。相反,您使用 setFieldError 强制性地将新名称 属性 添加到 errors 对象,但 firebaseErrorMessage 不是您表单中的字段。 (分享您的 initialValues 对象以验证这一点。)

其中一个烦人的部分是,可能有一些与 <ErrorMessage> 相关的样式您无法直接利用。但是,在我看来,正确构建系统可能更为重要,然后您可以根据需要模仿样式。

这是我的代码建议:

const RenderForm = ({ isSubmitting, isValid, status }) => (
  <Form>
    <h3>Sign Up</h3>
    <Email name="email" />
    <Password name="password" />
    <Button disabled={!isValid || isSubmitting} type="submit">
      Submit
    </Button>
    {status.firebaseErrorMessage && <p>{status.firebaseErrorMessage}</p>}
  </Form>
);

export const LoginForm = () => {
  async function authenticateUser(values, setStatus, setSubmitting) {
    const { email, password } = values;

    setSubmitting(true);

    try {
      await firebase.login(email, password);
      navigate("/", { replace: true });
    } catch (error) {
      console.log("Authentication Error: ", error);
      setStatus({
        firebaseErrorMessage: error.message
      });
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <>
      <h1>Form</h1>
      <Formik
        render={props => <RenderForm {...props} />}
        initialValues={initialValues}
        validationSchema={validationSchema}
        onSubmit={async (values, { setStatus, setSubmitting, resetForm }) => {
          await authenticateUser(values, setStatus, setSubmitting);
          resetForm();
        }}
      />
    </>
  );
};