jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
33.98k stars 2.79k forks source link

Using setFieldValue makes formik props unreliable #617

Open tetslee opened 6 years ago

tetslee commented 6 years ago

Describe the bug When using setFieldValue, the isValid and errors props in the form component will be not be updated until the next React update loop making them temporarily not representative of the current values.

Expected behaviour isValid and errors should always reflect the result of running validate on the current values

Suggested solution(s) In setFieldValue, we could put runValidations() before the setState call. This would make it more consistent with handleChange.


jaredpalmer commented 6 years ago

Hey thanks for the demo. Feel free to submit a PR!

timc13 commented 6 years ago

I think this could be nicely solved if we expose a callback from the setState call under the hood.

https://github.com/jaredpalmer/formik/issues/529

jaredpalmer commented 6 years ago

Yeah I think exposing the callback makes sense

tetslee commented 6 years ago

I'm not sure if we're thinking about the same issue since I don't think a callback will solve this (although that would also be nice to have). I'll try to describe my issue better.

The problem is calling setState({values}) inside of setFieldValue triggers a re-render before the validations have been run, so the underlying form component would go through a render with the updated values before the isValid and errors props have been updated to match. So we can't rely on isValid and errors to be representative of the current values.

See the console tab of the demo to see an example of this - when the input changes between valid and invalid there is one render call where the validation doesn't match the values, then it immediately re-renders with correct validation.

We don't have the same problem when using handleChange because React 16 batches setState calls within synthetic event handlers, both errors and values get updated together despite being in separate setState calls. My original suggestion above doesn't work because setFieldValue is not a synthetic event handler.

The options I can see are:

  1. Use ReactDOM.unstable_batchedUpdates like in #619
  2. Implement shouldComponentUpdate (something like this)
  3. Refactor so that only one setState call is made inside of setFieldValue, i.e. remove all setState calls from runValidations and instead pass the errors back to setFieldValue so we can do setState({isValid, errors, values}).
stale[bot] commented 6 years ago

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.

stale[bot] commented 6 years ago

ProBot automatically closed this due to inactivity. Holler if this is a mistake, and we'll re-open it.

lorenamelor commented 3 years ago

I have the same problem. Any updates ?

JoshBowdenConcepts commented 3 years ago

Hey I noticed the stale tag was removed but the ticket wasn't reopened. I see the message from the bot could this be addressed again? Also the stale bot doesn't say who to DM but.

johnrom commented 3 years ago

Tracked as part of v3, I'm on mobile but look up v3 Umbrella issue.

My implementation adds getState function to get a current ref of Formik's values at any time and the Formik API uses that internally instead of the render value.