formik: Incorrect validation if setFieldTouched is executed immediatly after setFieldValue
🐛 Bug report
Current Behavior
There is an issue with calling setFieldTouched, setTouched, or onBlur immediatly after updating the form values.
Due to using state.values here and here, any state change has to be commited (re-rendered) before a call to setFieldTouched, setTouched, or onBlur, otherwise the previous values will be validated instead.
This looks to be the same issue as #106, and is likely a regression that occured during the v2 hooks rewrite.
Expected behavior
Calling setFieldTouched immediatly after setFieldValue should not result in incorrect validation.
Reproducible example
https://codesandbox.io/s/formik-codesandbox-template-htdsu?file=/index.js
- @material-ui/pickers calls
onChangeandonAcceptsynchrounsly when selecting a date.onBluris only called when the input itself is blurred. - react-datepicker calls
onChangeandonSelectsynchrounsly when selecting a date.onBluris only called when the input itself is blurred.
Suggested solution(s)
Additional context
https://github.com/jaredpalmer/formik/issues/2432 https://github.com/jaredpalmer/formik/issues/106
Fix in v1: https://github.com/jaredpalmer/formik/pull/176
Your environment
| Software | Version(s) |
|---|---|
| Formik | 2.1.4 |
| React | 16.13.1 |
| TypeScript | |
| Browser | |
| npm/Yarn | |
| Operating System |
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 30
- Comments: 16 (1 by maintainers)
For those that come across this issue you can also temporarily solve this race condition this way:
Getting the same issue when using
formik-material-ui-pickers. Found a temporary workaround which seems to work so far -setFieldTouched(fieldName, true, false)in theonAcceptcallback. The 3rd parameterfalsemakes formik skip validation on that call, so instead it would get the validation result from the earliersetFieldValuecall (which, presumably, has the correct values).As @KristijanKanalas mentioned,
setFieldValuewill return a promise so his workaround fixes it. Although, for example in case you’d like async/await style:They either do actual same result
Was trying to track down this issue for hours in my app. Nice find @skoging… hopefully this gets addressed soon.
You would think not if you look at the types it’s defined as
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void;but in the actual implementation it does in fact return a promise. A simple console.log confirms it, and that’s why this solution works. To be fair it might be easily broken in the future if they change the implementation so I don’t wholeheartedly recommend this but it is a working solution for now.I have some trouble in my project. This issue blocks me from using Formik. Waiting for resolve.