Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying Value of setFieldErrors Using ErrorMessage Component in Formik

Tags:

reactjs

formik

See Update Below

I have a Login Form Component that I built using Formik that syncs with Firebase Authentication. I have set it up so that I can display errors from Firebase using the setFieldError prop. Here is the relevant sections of the code:

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>
)

Now, this works just fine. However, if I try to display the error message using Formik's ErrorMessage component, then the message does not show up.

In other words, this works:

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

This does not work:

<ErrorMessage name="firebaseErrorMessage" />

Any idea why this doesn't work and how to get it to work?

Thanks.

UPDATE

Here are my initial values:

const initialValues = {
  email: '',
  password: '',
}
like image 991
Moshe Avatar asked Mar 04 '23 09:03

Moshe


1 Answers

I don't think that you should use Formik's error for your Firebase error. Formik's errors are meant for validating form inputs.

To store and reference an API error, you can use Formik's status object. Handling API errors is the example he gives for status.

I think the issue is that, in Formik, name is meant to refer to the name of an input. Instead, you're imperatively adding a new name property to the errors object using setFieldError, but firebaseErrorMessage isn't a field in your form. (Share your initialValues object to verify this.)

One annoying part of this is that there is probably some styling associated with <ErrorMessage> that you can't leverage directly. But, in my opinion, it's probably more important to have your system structured correctly, and then you can mimic styles as-needed.

Here's my code suggestion:

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();
        }}
      />
    </>
  );
};
like image 73
Reed Dunkle Avatar answered May 05 '23 09:05

Reed Dunkle