jaredpalmer / formik

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

Own Field-level Validation: `formik.onChange` handler is not in sync with the `formik.values.confirmPassword` #3374

Open handhikadj opened 3 years ago

handhikadj commented 3 years ago

Bug report

Current Behavior

I came up with something that can handle field level validation but I notice the confirm password always fails because the formik.values.confirmPassword value is not "in sync" with its current value on the console And I think it's related to https://github.com/formium/formik/issues/3368 and https://github.com/formium/formik/issues/1737

onChange={(e) => {
  formik.handleChange(e);
  formik.validateField("confirmPassword");
  console.log(formik.values.confirmPassword);
}}

Expected behavior

the validation runs fine

Reproducible example

https://codesandbox.io/s/pedantic-cloud-skr3r

  1. type password
  2. type confirm password

you will see the validation fails and the value on console is not in sync

Suggested solution(s)

Additional context

Your environment

Software Version(s)
Formik 2.2.9
React latest
TypeScript -
Browser Chrome
npm/Yarn 6.14.13
Operating System Mac M1
johnrom commented 3 years ago

This is fixed in #3231

https://codesandbox.io/s/falling-platform-wxw9e?file=/src/App.js:1057-1108

handhikadj commented 3 years ago

noticed that there's this dependency: https://www.npmjs.com/package/@johnrom/formik-v3 I think we can say it's not officially fixed (at least yet)

johnrom commented 3 years ago

yes, the PR is still open

JulianKingman commented 2 years ago

@johnrom could you say roughly what the fix is? I'm happy to make a PR to v2 with a fix, but having a starting point or a commit to look at would make it a lot easier.

johnrom commented 2 years ago

The fix is my PR called Formik v3 Umbrella PR. The issue is that there is no way to retrieve the final state in v2 without waiting for the reducer to process messages and trigger an effect. In my v3 PR, I added a redux-like getState API which can be used to get the latest value immediately after an update.

JulianKingman commented 2 years ago

OK, I figured out what was going wrong. I'm not sure I'll make PR, but at least I can help others with this problem work around the issue. Maybe a PR to the docs about switching from 1x to 2x would do the trick.

The issue is that if you use setFieldValue as a substitute for onChange from v1, like this:

// initialValues = {A: undefined, B: 2, C: 3}
setFieldValue('A', 1);
setFieldValue('B', 2);
setFieldValue('C', 3);

It's setting the fields values asynchronously, but validating synchronously, so when setFieldValue('B', 2) runs, A is still undefined, but validation runs on it, and thus you get a corresponding error that A is undefined. Instead, I fixed it by doing this instead:

setValues({
  ...values,
  A: 1,
  B: 2,
  C: 3,
})
JulianKingman commented 2 years ago

I added a PR to the docs: https://github.com/jaredpalmer/formik/pull/3464

It addresses this: https://github.com/jaredpalmer/formik/issues/3345 And relates to this: https://github.com/jaredpalmer/formik/issues/2083

I'm right that setFieldValue is and is intended to be asynchronous with regards to the form values, right? Perhaps I should add a sentence about that to the docs for setFieldValue?