formik icon indicating copy to clipboard operation
formik copied to clipboard

[v2] isSubmitting resets to false too early.

Open rafaelderolez opened this issue 6 years ago • 32 comments

🐛 Bug report

Current Behavior

In 2.0.1-rc12, when submitting the form, isSubmitting is set to true but is instantly reset to false, making it hard to disable input fields and buttons.

Expected behavior

I would expect isSubmitting to be true until it's set to false in the onSubmit function.

Reproducible example

Codesandbox example. (Sandbox was deleted at some point, sorry)

Your environment

Software Version(s)
Formik 2.0.1-rc12
React 16.8.6
Browser Google Chrome Version 76.0.3809.87 (64-bit)
npm/Yarn 1.17.3
Operating System macOS 10.14.5

rafaelderolez avatar Aug 06 '19 12:08 rafaelderolez

I just ran into this issue as well.

tobeycodes avatar Aug 09 '19 01:08 tobeycodes

Confirmed

jaredpalmer avatar Aug 16 '19 22:08 jaredpalmer

I ran into the issue as well and noticed that it works as I would expect if my onSubmit function returns a promise. isSubmitting is set to false first when the promise resolves.

karlandin avatar Aug 18 '19 19:08 karlandin

What is the expected here? Toggling state on promise resolution makes sense but signature of submitHandler is (values: Values, formikBag: FormikBag) => void. Perhaps it should also accept (values: Values, formikBag: FormikBag) => Promise<T> and do what it does now?

shulcsm avatar Sep 05 '19 13:09 shulcsm

Ran into this problem when implementing modal forms too in #1741.

Ericnr avatar Sep 06 '19 13:09 Ericnr

Thanks for the write up. Will investigate

jaredpalmer avatar Sep 07 '19 13:09 jaredpalmer

This is exactly my problem. Did anyone came-up with a workaround?

michielmetcake avatar Sep 12 '19 12:09 michielmetcake

I had a similar issue in v1.5.8 which I was able to resolve by setting enableReinitialize to its default value false.

mhienle avatar Sep 26 '19 13:09 mhienle

any updates on this issue? I'm having the same problem and it's causing issues disabling the submit button for me - breaking functionality. Setting enableReinitialize to false as suggested by @mhienle did not help :(

UPDATE: It seems that if I use async/await this works correctly

<Formik
    initialValues={{ email: '' }}
    enableReinitialize={true}
    validationSchema={Yup.object({
      email: Yup.string()
        .email('Invalid email addresss`')
        .required('Required'),
    })}
    onSubmit={async(values, { setSubmitting }) => {
      console.log('submit')
      await callApi()
    }}
  >
    <Form>
      <Field type="email" name="email" />
      <ErrorMessage name="email" component="div" />
      <SubmitButton />
    </Form>
  </Formik>

note i don't use setSubmitting anywhere - it just seems to do it's thing all on it's own :S

alexborisov avatar Oct 26 '19 20:10 alexborisov

@alexborisov did you try return await callApi()

As someone else suggested in my case my operation was async and I wasn't returning the promise. Seems like that would even be the intended behavior. If the onSubmit method doesn't return a promise it would assume it's done with the work.

danecando avatar Oct 28 '19 01:10 danecando

@danecando yup returning async works for me. As does returning a promise. Thanks!

alexborisov avatar Oct 28 '19 11:10 alexborisov

Do we need to update the docs around this?

jaredpalmer avatar Oct 28 '19 15:10 jaredpalmer

Perhaps in the tutorial as well?

jaredpalmer avatar Oct 28 '19 15:10 jaredpalmer

@jaredpalmer I believe it would be worth mentioning. I think in a previous version it worked fine with me handling the submit state manually in my async callback but it didn't work that way for me on v2. Not sure if this is new behavior or my memory sucks but returning the promise seems like a simpler api to me anyways.

Let me know I'll be happy to submit a pr sometime this week mentioning this behavior in the docs. PS: v2 is the :bomb: great work jared and contributors.

danecando avatar Oct 29 '19 00:10 danecando

Here is an example of the issue. Just enter an email and click as many times as you can within 1 sec. See how submitCount increases.

https://codesandbox.io/s/formik-example-67mpu?fontsize=14

RodyGL avatar Oct 29 '19 01:10 RodyGL

Also facing this issue

socksrust avatar Oct 29 '19 12:10 socksrust

So returning async seems to work..

But how to handle dispatching redux actions on submit?

michielmetcake avatar Nov 01 '19 12:11 michielmetcake

Returning the promise solved my issue in case anyone else faces this issue.

omarshammas avatar Nov 01 '19 19:11 omarshammas

I am still getting the same problem, any solutions please?

ruzolut avatar Nov 08 '19 13:11 ruzolut

Related to #1957 and #1987 sounds like

willxy avatar Nov 08 '19 15:11 willxy

You should follow this approach https://github.com/relayjs/relay-examples/pull/118

you need both, ref and state to avoid double clicks/submits

sibelius avatar Nov 11 '19 15:11 sibelius

Confirmed

Hi,

I just experienced this on "formik": "^2.0.4" as well. What is the fix for this?

kevinvugts avatar Nov 13 '19 16:11 kevinvugts

What's the suggested solution here?

jaredpalmer avatar Nov 14 '19 19:11 jaredpalmer

also this https://twitter.com/davidkpiano/status/1194616763000008705?s=21

we can return isSubmitting to user (to use as disabled on buttons), and use a ref to avoid double handleSubmit calls (this ref could be only for internal use)

sibelius avatar Nov 14 '19 19:11 sibelius

@jaredpalmer #1987 is the solution many of us are hoping would be accepted which would allow many of us to not have to change the way we currently handle isSubmitting in v1.5.8. However, we're unsure if this is something you actually support. Otherwise, many of us have reverted to v1.5.8 for now. Thanks for taking a look at this!

j0b0sapi3n avatar Nov 14 '19 19:11 j0b0sapi3n

@jaredpalmer So now that the isSubmitting state of Formik is controlled by the promise return in OnSubmit handler don't you think that exposing the setSubmitting method is stale.

kush3107 avatar Nov 24 '19 07:11 kush3107

@jaredpalmer So now that the isSubmitting state of Formik is controlled by the promise return in OnSubmit handler don't you think that exposing the setSubmitting method is stale.

It's not. As the release note of v2.0.5 says:

HOWEVER, if your onSubmit function is synchronous (e.g. v1), then you need to still call setSubmitting(false) on your own

gustavopch avatar Nov 24 '19 13:11 gustavopch

updating the documentation to mention that "Returning the promise" will give isSubmitting a better, not flakey value of the form's submittion state - would be awesome

So returning async seems to work..

But how to handle dispatching redux actions on submit?

@michielmetcake Have you tried something like:

const onSubmit={() => {
    return new Promise((resolve, reject) => {
      dispatchYourActions({type: '', value: [], resolve, reject, ...anyOtherData?})
      // Make sure your action calls resolve or reject!
    })
  }}

sgnl avatar Feb 22 '20 02:02 sgnl

I use redux-thunk and this works for me. Make sure your action returns a promise aswell!

  const handleSubmit = (values, {setSubmitting}) => {
    setSubmitting(true);
    return dispatch(myAction(values))
      .then(() => {
        setSubmitting(false);
        return Promise.resolve();
      })
  }

j-waaang avatar May 07 '20 15:05 j-waaang

@jaredpalmer So now that the isSubmitting state of Formik is controlled by the promise return in OnSubmit handler don't you think that exposing the setSubmitting method is stale.

It's not. As the release note of v2.0.5 says:

HOWEVER, if your onSubmit function is synchronous (e.g. v1), then you need to still call setSubmitting(false) on your own

But still not works

kaluabentes-hotmart avatar Dec 01 '21 01:12 kaluabentes-hotmart