Отображение значения setFieldErrors с помощью компонента ErrorMessage в Formik - PullRequest
1 голос
/ 22 сентября 2019

См. Обновление ниже

У меня есть компонент формы входа, который я создал с помощью Formik, который синхронизируется с Аутентификацией Firebase.Я настроил его так, чтобы я мог отображать ошибки из Firebase, используя setFieldError prop.Вот соответствующие разделы кода:

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 Ответ

1 голос
/ 22 сентября 2019

Я не думаю, что вы должны использовать ошибку Formik для вашей ошибки в базе данных.Ошибки Formik предназначены для проверки входных данных формы.Чтобы сохранить и ссылаться на ошибку API, я бы useState.

ОБНОВЛЕНИЕ: вместо useState, вы можете использовать Formik's statusobject. Обработка ошибок API - это пример, который он приводит для status.

Я думаю, проблема в том, что в Formik name означает ссылку на имя входа.Вместо этого вы обязательно добавляете новое свойство name к объекту errors, используя setFieldError, но 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();
        }}
      />
    </>
  );
};
...