Open andycarrell opened 4 years ago
I'd like to help with this
Go for it!
I'd like to help with this
Any progress on this?
Yeah. Putting up a PR in a couple of days
@omkar-joshi is there any progress on this? If you're still working on the PR, I would really appreciate if you could explain any workarounds for this issue at this time. Also, is there any way to prevent Formik from setting errors after running validateOnMount
. I would like to set the isValid value, but not have errors on the fields. Thanks for your anticipated help.
Yeah. Putting up a PR in a couple of days
Hi @omkar-joshi any update on this? appreciate your contribution towards OSS.
Is it just a case of using validateFormWithHighPriority
instead of validateFormWithLowPriority
? https://github.com/jaredpalmer/formik/blob/f117c04738ed218b5eb8916d7189e0849962d50d/packages/formik/src/Formik.tsx#L366-L370
π Hi @semopz I've been looking into this a bit this weekend, and I don't think high/low priority will fix this issue unfortunately. Both validate form functions (withLow...
/ withHigh...
) call runAllValidations
which runs asynchronously - so from mount until that promise resolves, isValid
will be true
. This can cause an unideal user experience, specifically if isValid
is used to drive form appearance, for example disabling the submit button. As a consumer of formik, I need to know what to render while validation on mount is running π€
Some possible solutions (in user-land or in the library) I can think of are:
initialErrors
, then renderisInitialValid
- to set isValid whilst validation on mount is runningisValidating
to true initially, then use this value to determine what to render. (I've coded this here to show how)Not really sure how to proceed with this, I understand to an extent why isInitialValid was deprecated, but also think removing it isn't serving us well in this scenario.
Here are a few options in my view:
Option 1:
Option 2:
isInitialValid
and only issue a warning if the user uses more than one of { isInitialValid
, validateOnMount
, and initialErrors
}, which could result in conflicting validation states & thus render flashing. IMO this is the simplest and best option. But it does not account for cases where we legitimately need to do an async call in order to compute whether the initial state is valid. (But really, do these cases even exist in the wild? I can't think of a real-world example where an async-validated form doesn't know its initial validation state on initial render. In fact it seems like in "80%" of cases, the initial state is invalid, so it seems like isInitialValid
should have been defaulting to false
this whole time!)If people think that Option 2 makes sense, I can send a PR.
I stick on option 2 and use isInitialValid. It fits my needs, it's a simple props to disable a submit button before user completes fields π
Ultimately the state of isValid
cannot be known until validation completes, unless it is explicitly provided (which defeats the purpose of validateOnMount
).
Where I have experienced this issue, and likely where many others have, is in trying to control enabled/disabled state of a submit button.
Typically the button would be disabled while validations are running. The logic would therefore be disabled={isValidating || !isValid}
.
The problem is that isValidating
is false
on initial render even when validateOnMount
is set to true. This seems counterintuitive. Having isValidating
default to true
when validateOnMount
is true
would likely allow most of us to work around this issue.
Status?
To add to this discussion, it seems the problem is because computing isValid
dependent on dirty
, but dirty is already set to true before the form finishes its first validation - this.state.errors
is still empty at this point, computing isValid
to true when it shouldn't be.
https://github.com/formium/formik/blob/master/packages/formik/src/Formik.tsx#L940-L950
one possible solution is:
validated
flag (as a global, or part of the state, not sure) that gets set to true when runAllValidations
resolvesisValid
computation depend on flag validated
const isValid = dirty && validated ? ...
if this makes sense, i can submit a PR
@vai0 I like your approach. Are you still open for submitting this PR?
@vai0 push π€
Jan 6, 2020 π
Any solutions or workarounds?
π Bug report
Current Behavior
When
validateOnMount
is true, initial value forisValid
is 'true', then validation occurs on initial values (which could setisValid
to 'false').Screenshot taken from reproducible example - see console for inconsistency -
isValid
has a different value, for the same form value (empty string in the example):Expected behavior
The first render should return the result of validating the initial values for isValid.
Reproducible example
https://codesandbox.io/s/formik-codesandbox-template-kegrs
Additional context
Would this problem be solved by setting initial errors? I believe possibly, although that would require running validation manually, defeating the purpose of validateOnMount.
The example is a simplification - application code has a far more complex validation schema + more initial values.
Your environment