7
votes

I am catching errors from api and showing them in form, and that is working fine. But the problem is when I change one field in form all errors disappear. For form I am using Formik and for validation Yup.

const handleSubmit = (values, {setSubmitting,  setFieldError, setStatus}) => {
    someApiCall(values)
        .then(
            () => {

            },
            (error) => {
                // example of setting error
                setFieldError('email', 'email is already used');
            })
        .finally(() => {
            setSubmitting(false)
        });
};

I tried with adding third parametar false to setFieldError, but nothing changed.

2
Formik + Yup brings you live validation with a schema. what do you want handle with API ? field type errors or other things ?! like duplicated data or not found etc.Alex
i have validation on frontend thanks to yup, but for example when i got error from api that email is already taken i want to show that error also, and i am showing it, but when i change some other field like firstName, error that was on email disappears, and it shoud disappear only if i am changing email fieldbobby
@bobby let me know if the answer posted helps for future users who may encounter similar problemRikin

2 Answers

7
votes

Here's my working example: https://codesandbox.io/s/formik-example-dynamic-server-rendered-values-1uv4l

There's a callback validate available in Formik: https://jaredpalmer.com/formik/docs/api/formik#validate-values-values-formikerrors-values-promise-any using which you can probably try to do something like below.

I initiated emailsAlreadyInUse with empty array and then in your API call once error gets returned then add that user to the array and once user uses the same email again and tried to validate, although it will pass Yup validation but it will be caught in validate callback which I believe runs after Yup validation (though I could be wrong but in your case doesn't matter).

const emailsAlreadyInUse= [];
const handleSubmit = (values, {
  setSubmitting,
  setFieldError,
  setStatus
}) => {
  someApiCall(values)
    .then(
      () => {
        // Do something
        // possibly reset emailsAlreadyInUse if needed unless component is going to be unmounted.
      },
      (error) => {
        // example of setting error
        setFieldError('email', 'email is already used');
        // Assuming error object you receive has data object that has email property
        emailsAlreadyInUse.push(error.data.email);
      })
    .finally(() => {
      setSubmitting(false)
    });
};

<Formik
...
...
validate = {
  values => {
    let errors = {};
    if (emailsAlreadyInUse.includes(values.email)) {
      errors.email = 'email is already used';
    }
    return errors;
  }
}
/>
2
votes

I founded simplier method to make API validation errors always visible than using validate method. You can set validateOnBlur and validateOnChange on your form to false. It will cause validation only on submit and errors returned from API will remain after changing field value.

Usage:

<Formik
        initialValues={initialValues}
        onSubmit={handleSubmit}
        validateOnBlur={false}
        validateOnChange={false}
      >
...form fields...
</Formik>