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

时间:2019-09-22 13:37:23

标签: reactjs 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: '',
}

1 个答案:

答案 0 :(得分:1)

我认为您不应该将Formik的错误用于Firebase错误。 Formik的错误旨在验证表单输入。要存储和引用API错误,我会useState

更新:您可以使用Formik的status对象代替useState处理API错误是他为status提供的示例。

我认为问题是在Formik中,name是指输入的名称。相反,您必须使用errorssetFieldError对象添加一个新的name属性,但是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();
        }}
      />
    </>
  );
};