formik: Add form-global error key (e.g. _form)

Is your feature request related to a problem? Please describe.

Sometimes the call to API back-end fails with an error that is not related to a specific field (e.g. a 404). In that case, setErrors is not applicable. I could use setStatus but that requires some extra checks and some extra handling in the form display.

Describe the solution you’d like

Allow setting a global form error with a specific key (e.g. _form, like [redux-form’(https://redux-form.com/7.4.2/docs/api/reduxform.md/#-code-onsubmit-function-code-optional-)) and make it available as a prop, for instance error (again, keeping the same naming as redux-form).

const InnerForm = ({
  values,
  errors,
  error,
  touched,
  handleChange,
  handleBlur,
  handleSubmit,
  isSubmitting,
}) => (
  <form onSubmit={handleSubmit}>
    { error && <div>{error}</div> }
    <input
      type="email"
      name="email"
      onChange={handleChange}
      onBlur={handleBlur}
      value={values.email}
    />
    {touched.email && errors.email && <div>{errors.email}</div>}
    <button type="submit" disabled={isSubmitting}>
      Submit
    </button>
  </form>
);

const MyForm = withFormik({
  mapPropsToValues: props => ({ email: '', password: '' }),
  handleSubmit: (
    values,
    {
      props,
      setSubmitting,
      setErrors,
    }
  ) => {
    LoginToMyApp(values).then(
      user => {
        setSubmitting(false);
      },
      errors => {
        setSubmitting(false);
        setErrors(transformMyApiErrors(errors));
      }
    );
  },
})(InnerForm);

Describe alternatives you’ve considered

As said above, in theory you can use setStatus, but that requires more setup:

const InnerForm = ({
  values,
  errors,
  status,
  touched,
  handleChange,
  handleBlur,
  handleSubmit,
  isSubmitting,
}) => (
  <form onSubmit={handleSubmit}>
    { status && status.error && <div>{error}</div> }
    <input
      type="email"
      name="email"
      onChange={handleChange}
      onBlur={handleBlur}
      value={values.email}
    />
    {touched.email && errors.email && <div>{errors.email}</div>}
    <button type="submit" disabled={isSubmitting}>
      Submit
    </button>
  </form>
);

const MyForm = withFormik({
  mapPropsToValues: props => ({ email: '', password: '' }),
  handleSubmit: (
    values,
    {
      props,
      setSubmitting,
      setErrors,
      setStatus,
    }
  ) => {
    LoginToMyApp(values).then(
      user => {
        setSubmitting(false);
      },
      errors => {
        setSubmitting(false);
        if (errors.status_code !== 400) {
          setStatus({error: errors})
        }
        else {
          setErrors(transformMyApiErrors(errors));
        }
      }
    );
  },
})(InnerForm);

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 51
  • Comments: 23 (2 by maintainers)

Most upvoted comments

Still think this is important !

On Tue 30 Oct 2018 at 03:11, stale[bot] notifications@github.com wrote:

Hola! So here’s the deal, between open source and my day job and life and what not, I have a lot to manage, so I use a GitHub bot to automate a few things here and there. This particular GitHub bot is going to mark this as stale because it has not had recent activity for a while. It will be closed if no further activity occurs in a few days. Do not take this personally–seriously–this is a completely automated action. If this is a mistake, just make a comment, DM me, send a carrier pidgeon, or a smoke signal.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jaredpalmer/formik/issues/711#issuecomment-434146267, or mute the thread https://github.com/notifications/unsubscribe-auth/AAHWtW09LLYWEBbClngE1jNlDTEj4_Faks5up7VNgaJpZM4U3rnw .

Just my two cents that this indeed should be added. There are some cases where the error isn’t tied to a specific field and we’re displaying an alert box above the form.

Would love to see this implemented still. Would make things a lot cleaner. Really lacking when compared to final-form.

Hola! So here’s the deal, between open source and my day job and life and what not, I have a lot to manage, so I use a GitHub bot to automate a few things here and there. This particular GitHub bot is going to mark this as stale because it has not had recent activity for a while. It will be closed if no further activity occurs in a few days. Do not take this personally–seriously–this is a completely automated action. If this is a mistake, just make a comment, DM me, send a carrier pidgeon, or a smoke signal.

I think mixing field errors and form errors is less graceful since form-level errors are often API or app-level errors whereas field errors are generally fixable user errors. I think instead of would make sense to add a new place for an array of form errors. Currently, status can be used for this since it is just a bag of whatever the developer wants. It doesn’t get used for validation, but it can manually be checked in the submit fn. API errors aren’t generally used for form validation anyway, but to alert the user to something.

If the error depends on the user changing something (validation), the error should be added to the field that needs changing.

Given all these variables, to me it makes sense to add this as a plugin or wrapper which can be more configurable than adding it to Formik’s core functionality, which would prescribe a certain way of handling these scenarios.

Still interested in a fix like this. Now using the @defunctzombie workaround adding an error field, but it’s not really optimal.

Hey,

Just want to mention that with hooks it’s easy to add this feature on top of formik. Here is an example I have for my app where I try to share/reuse the global error / onSubmit logic which is quite often always the same


type AppFormikConfig<Values extends object, Result = any> = Omit<
  FormikConfig<Values>,
  'onSubmit'
> & {
  submitAppForm: (values: Values) => Promise<Result>;
  onSubmitSuccess?: (result: Result) => void;
};

export const useAppFormik = <Values extends object, Result = any>(
  config: AppFormikConfig<Values, Result>,
) => {
  const { submitAppForm, onSubmitSuccess, ...otherFormikConfig } = config;
  const [globalError, setGlobalError] = useState<string | null>(null);

  const onSubmit = async (values: Values, actions: FormikHelpers<Values>) => {
    console.debug('onSubmit', values);
    actions.setSubmitting(true);
    setGlobalError(null);
    try {
      const result: Result = await submitAppForm(values);
      console.debug('form submitted successfully', { values, result });
      form.resetForm();
      onSubmitSuccess && onSubmitSuccess(result); //TODO give default user feedback on success?
    } catch (e) {
      if (isAPIResponseDataError(e)) {
        console.debug('Reponse errors', e.response.data);
        form.setErrors(e.response.data);
        if (e.response.data.general) {
          setGlobalError(e.response.data.general);
        }
      } else {
        console.error('error', e);
        setGlobalError('Erreur technique: ' + e.message); // TODO how to handle those errors?
      }
    } finally {
      actions.setSubmitting(false);
    }
  };

  const form = useFormik<Values>({
    ...otherFormikConfig,
    onSubmit,
  });

  return { form, globalError };
};

A workaround that I found simple and effective has been to add an error field to my form properties as a placeholder field for attaching general form errors. I can set the error value of this and use the <ErrorMessage> component to place the error where appropriate for the overall form.

This! I just came to drop a comment and say I’d love to see this feature in formik. I would definitely like to be able to handle unexpected API errors not really related to any of the fields.

Would still like your opinion on ^ 😃