Re-mounting a Field component erases the field-level validation function
Closed this issue ยท 19 comments
Are you submitting a bug report or a feature request?
Bug report
What is the current behavior?
When a Field with a field-level validation function attached to it is unmounted and immediately re-mounted, that validation function will never be run again.
In the example below, when the key changes, the Field will be unmounted and re-mounted, and the validation function will never be run again:
<Field
key={`${this.state.firstNameFieldKey}`}
component={renderField}
name="firstName"
validate={this.validateFirstNameField}
/>
Perhaps a more common method of unmounting and remounting fields is conditional rendering of fields with the same name. In the example below, when this.state.shouldRenderTextArea changes, the validate function will never be run again:
const FirstNameTextArea = () => (
<Field
name="firstName"
component={renderTextArea}
validate={validateFirstNameField}
/>
);
const FirstNameTextField = () => (
<Field
name="firstName"
component={renderTextField}
validate={validateFirstNameField}
/>
);
/*In the form's render method: */
{
this.state.shouldRenderTextArea ?
<FirstNameTextArea />
:
<FirstNameTextField />
}
What is the expected behavior?
After the field is re-mounted, its validation function should run.
Sandbox Link
https://codesandbox.io/s/m7l1lyzyoy
What's your environment?
redux-form 7.1.1
react 16.0.0
Other information
The problem appears to be that Field registers the validate function in componentWillMount, and erases the validate function in componentWillUnmount. However, React 16 will always run componentWillMount of the new component BEFORE componentWillUnmount of the old component. That means that we register the new validate function, and immediately delete it.
Would there be any problem with having Field register itself it componentDidMount instead?
Status on this?
To add some context: I get the same problem on all 7.x.x versions. Works as expected on 6.8.0
React: 15.6.2
Yes, I have the same problem. It was because componentWillUnmount call after componentWillMount.
-> componentWillMount First
--- Start Remounting
-> componentWillMount Second
-> componentWillUnmount First
I think redux-form must call register function when componentDidMount. I can try make PR for this? But I don't know what's can broke if register function will move in componentDidMount...
related links:
I solve this problem via destroyOnUnmount: false, but I don't know what's wrong if you use it in your own project.
I used destroyOnUnmount: false too as a temporary workaround, but a side-effect is that the form keep the submitted values as initialValues...
Any news on this?
Hi folks, I also have this issue. Thanks to @Luchanso , I am using workaround. Do you have any news on this issue?
I can't use the destroyOnUnmount
workaround because we need to destroy other form values on unmount. Is there any way to target this prop against a single field on the form?
@Elliot128 we also had same issue. We first thought about clearing values by firing change action, but this approach will keep the validation errors. So we decided to register/deregister fields manually, until we find a good solution.
@erikras @gustavohenke
I tested that the referenced @viljark PR #3909 merge helps, but doesn't fix this issue.
I think @sandkampderek suggestion to use componentDidMount
to register Field is correct. Because React 16 calls componentDidUnmount
after componentWillMount
and the new Field is unregistered immediately.
I tested registering Field in componentDidMount
instead of componentWillMount
and the Field validation was fixed.
Reactjs docs say that we should avoid componentWillMount
and use componentDidMount
for any side-effects or subscriptions. In react 17 componentWillMount
is scheduled to be deleted.
https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
"Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead."
@erikras @gustavohenke
What do you think would it be possible to register Field in componentDidMount
instead of componentWillMount
to fix this issue?
Seems that we should use componentDidMount
When using React strict mode:
<React.StrictMode>
<App/>
</React.StrictMode>
Then error is printed to console:
componentWillMount: Please update the following components to use componentDidMount instead:
I met this issue as well, but I found a intreating solution:
not working below:
const ConditionalComponent = () => someCondition? <ReduxFormFieldComponentOne /> : <ReduxFormFieldComponentTwo />;
render() {
<ConditionalComponent />
}
working below:
const ConditionalComponent = () => someCondition? <ReduxFormFieldComponentOne /> : <ReduxFormFieldComponentTwo />;
render() {
{ConditionalComponent()}
}
Someone can explain this? The only diff is one use < />, another one use {func()}
@erikras
As redux-form still uses unsafeComponentWillMount
. See https://github.com/erikras/redux-form/blob/master/src/createField.js#L41
I think this isn't fixed.
This issue initial comment. See: #3566 (comment)
The problem appears to be that Field registers the validate function in componentWillMount, and erases the validate function in componentWillUnmount. However, React 16 will always run componentWillMount of the new component BEFORE componentWillUnmount of the old component. That means that we register the new validate function, and immediately delete it.
Would there be any problem with having Field register itself it componentDidMount instead?
Hi,
is this issue resolved? I am facing similar issue and still need to depend on onDestroyUnmount: false workaround.
Hi,
Having a similar issue here. Using version 7.4.2 with React 16.6.0 when setting field level validation it not only doesn't error, the entire field disappears if I don't input a value and I then tab through to the next field. onDestroyUnmount isn't helping either.
thanks for any help to resolve these issues
This issue is still reproducable on redux-form 8.2
enableReinitialize : true solve the issue
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.