2
votes

I'm having some issues for a couple days now where every error that I set in the onSubmit method of my Formik form are not added to the errors props. My specific issue is concerning the backend errors that are returned by the GraphQL API. I have a pretty long form so I won't post all of my code but the relevant code is as follows :

This is a snippet of my form :

<Formik
  initialValues={initialValues}
  validationSchema={validationSchema}
  onSubmit={onSubmit}
>
  {({ errors, setFieldValue, touched, values }) => (
    <>
      {console.log(errors)}

      <Form>
        <div className="divided-by-2">
          <div className="street-number-and-street">
            <FormikTextField
              id="streetNumber"
              name="streetNumber"
              label={i18next.t('model:traveler.streetNumber')}
            />
            <FormikTextField
              id="street"
              name="street"
              label={i18next.t('model:traveler.street')}
            />
          </div>

          <FormikTextField
            id="city"
            name="city"
            label={i18next.t('model:traveler.city')}
          />

          <FormikTextField
            id="zip"
            name="zip"
            label={i18next.t('model:traveler.postCode')}
          />
        </div>
      </Form>
    </>
  )}
</Formik>

The onSubmit is a function that I declared outside of the Formik declaration because it is quite extensive. It goes as follows :

const onSubmit = async (values, actions) => {
  const variables = {
    firstname: values.firstname,
    lastname: values.lastname,
    [The rest of my variables are also here including the ones in the above snippet]
  }

  const { data } = await profileUpdate({
    variables,
  });

  if (data.userUpdate.errors.length === 0) {
     const { data } = await usersRoleRequestCreate({
        variables: {
          role: 'explorer',
          note: values.note,
          token,
        },
      });

      if (data?.usersRoleRequestCreate?.errors.length > 0) {
        for (const error of data?.usersRoleRequestCreate?.errors) {
          console.log(error.attribute);
          const key = Mapping[error.attribute];
          if (key) {
            let message = '';
            for (const errorMessage of error.errors) {
              message += errorMessage.message;
            }
            actions.setFieldError(key, message)
          }
        }
    } else {
         [If no errors, success code here]
    }
  }
}

I have tried to use setFieldError as shown here but I also tried using setErrors, creating an object using useState to store my backend validation errors and then assigning those values to errors, all of which were unsuccessful. The only event in which errors has a value is when I receive frontend errors from the yup validationschema. The Formik documentation doesn't provide a lot of examples (https://formik.org/docs/api/formik) and I really can't figure it out.

Thank you for your help

1

1 Answers

0
votes

I had been working on this the whole day by now, and finally, I resolved it.

If you setFieldError and then the validation function is executed, those errors are overwritten. I don't know if this is the best solution, but for me is working.

const validate = (values) => {
        // let prevErr = formik.errors;
        const errors = {};
        console.log("inside validate", formik);
        if (!values.email) {
            if (!formik.errors.email) {
                errors.email = "Required";
            } else {
                errors.email = formik.errors.email;
            }
        } else if (
            !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
        ) {
            errors.email = "Invalid email address";
        }

        if (!values.password) {
            if (!formik.errors.email) {
                errors.password = "Required";
            } else {
                errors.password = formik.errors.password;
            }
        }

        return errors;
    };
const onError = (data) => {
        formik.setFieldError("email", "BackEnd Error");
        formik.setFieldError("password", "BackEnd Error");
    };

Things to try looking for your solution:

  • Initial values, must be setted
  • Console.log the form inside the validation function to see when the errors that you set are loaded on the form.
  • Take a look if the fields are touched
  • Maybe the validation function is executed more than two times and this end up overriding those errors because they are no longer there.

Let me know if any of this works, this is my first time posting a solution on Stack Overflow.

Thanks!