redux-form: handleSubmit ignores validation errors on unmounted fields
Hello,
I’ve just noticed that if I return an error from my validation function for a field which is not currently mounted, the error is ignored and the form is allowed to submit anyway.
The following code snippet isn’t a great use case example but it proves the behaviour:
@reduxForm({
form: 'simple',
validate: (values) => ({
firstName: !values.get('firstName') ? 'required' : undefined,
lastName: !values.get('lastName') ? 'required' : undefined,
}),
onSubmit: () => alert('submitting')
})
class SimpleForm extends React.Component {
render() {
return <div>
<Field name="firstName" component="input" type="text" />
<button type="submit" onClick={this.props.handleSubmit}>Submit</button>
</div>
}
}
This form should actually never submit as there is never a value for lastName. But it seems that because lastName doesn’t exist as a <Field> component, its errors are ignored and the form is allowed to submit as long as firstName is filled in. Add a lastName field and the issue goes away.
I would expect any error I return to prevent form submission. An error is an error. The <Field> components I have mounted are display logic only, the data in the store is the source of truth.
My particular use case is that I have a form composed of multiple tabs. With this behaviour, validation is effectively run only for the fields which are on the currently active tab.
Another use case would be hidden fields. I consider < input type=“hidden” > to be obsolete now that I’m using redux. My hidden fields are in the store so there’s no need to have them in the DOM.
Any thoughts? Thanks
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 7
- Comments: 23 (6 by maintainers)
Hmmm… that seems like a complex and arbitrary solution to a single problem.
In my eyes, the form is either valid or it is not valid. The rest is an implementation detail that should be left to the programmer. A wizard should be accomplished either by using multiple forms or by writing my own logic for partial validation.
Wouldn’t this work?
onSubmit should behave in one of two ways upon a submission attempt:
Anything in between is unpredictable. The behaviour “Do this if all fields currently in the DOM are valid” is unpredictable, opinionated and wierd.
@lustoykov I guess I over-complicated my response as I had created my own decorator to generalize it for all my forms and to accomplish some additional tasks as well.
When it comes down to it though, redux-form includes your validate function as a prop to your component, so there’s nothing stopping you from calling the validate function yourself before actually submitting your data.
I don’t remember all the details as I go through my code, but I think you’ll want to return a promise and reject it if there are errors, otherwise redux-form will see the submission as successful.
Also, I’ve simplified the above code by just having if (!errors) but you may have to do some processing of the errors to detect yes or no depending on what you actually return from your validate function.
I think the better solution is to allow validation on all fields rather than not unmounting fields. There’s a couple reasons for this:
The direct approach is to add a prop like
validateMountedFieldsOnly
(defaults totrue
) which will switch between validating all fields and validating only mounted fields.It seems like a reasonable change to me.
This is by design. Imagine you have a wizard-style multi-part form with a total of 20 fields. Each section of the overall form is 5 fields. After completing each of the 5 fields you click “Next”, which validates the currently mounted section of the form, then continues on to the next section.
If you were to check validity over the entire form while you were entering in the first 5 fields you would never be able to move on to the next 5 because the form would never be valid.
That being said, what you’re proposing isn’t necessarily poor logic or incorrect. I’m not opposed to there being a prop that you can pass to the form that would decided whether or not to validate all the fields or only the currently mounted fields, something like
validateAllFields
.