Similar to the issue #564 .
Just like in the above mentioned issue, I have a hidable form. The difference is: I have a ParentContainer that passes the visible prop to the ConnectedParent. Yet everything is fine unless I hide the Form dispatching asynchronously. In this case I get a warning:
setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the Connect(Form(Form)) component.
I'm sorry, but i can't provide a clonable example. Some code to reproduce this bug:
import React, { Component } from 'react';
import {connect} from 'react-redux';
import {Field, reduxForm} from 'redux-form';
const Form = () => <Field type="text" component="input" name="field" />;
const ReduxForm = reduxForm({ form: 'example' })(Form);
class Parent extends Component {
componentWillReceiveProps(newProps) {
if (this.props.visible !== newProps.visible) {
if (!newProps.visible) {
newProps.dispatch({ type: 'ANYTHING' });
}
}
}
render() {
return <div>{this.props.visible ? <ReduxForm /> : null}</div>;
}
}
const ConnectedParent = connect()(Parent);
const ParentContainer = ({ dispatch, visible }) => (
<div>
<ConnectedParent visible={visible} />
<button type="button" onClick={() => { dispatch({ type: 'SHOW_FORM' });} }>show</button>
<button type="button" onClick={() => { dispatch({ type: 'HIDE_FORM' });} }>hide</button>
<button type="button" onClick={() => { setTimeout(() => { dispatch({ type: 'HIDE_FORM' }); }, 0)} }>hide with timeout</button>
</div>
);
const mapStateToProps = state => ({ visible: state.app.form });
const ConnectedParentContainer = connect(mapStateToProps)(ParentContainer);
export default ConnectedParentContainer ;
Corresponding reducer:
const initialState = {
form: false,
};
export default (state = initialState, action) => {
switch (action.type) {
case 'SHOW_FORM':
return Object.assign({}, state, {
form: true,
});
case 'HIDE_FORM':
return Object.assign({}, state, {
form: false,
});
default:
return state;
}
};
Use the ConnectedParentContainer component and the reducer in your app.
Steps to reproduce:
1) Click "show" button.
2) Click "hide with timeout" button.
3) Experience the Warning.
@osigum Can you provide more details? What does you store creation look like? What does your top-level component look like? Are you using the latest versions of react/redux-form/etc? There's not quite enough here to troubleshoot without making assumptions.
I was able to repro the bug above. I refactored out redux-form and ended up with this:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Provider, connect } from 'react-redux';
import { createStore } from 'redux';
const store = createStore((state = { visible: false }, action) => {
switch (action.type) {
case 'SHOW_FORM': return { visible: true };
case 'HIDE_FORM': return { visible: false };
default: return state;
}
});
const AAA = () => <div>Hello</div>;
const BBB = connect(state => state)(AAA);
class CCC extends Component {
componentWillReceiveProps(newProps) {
if (this.props.visible && !newProps.visible) {
newProps.dispatch({ type: 'ANYTHING' });
}
}
render() {
return <div>{this.props.visible ? <BBB /> : null}</div>;
}
}
const DDD = connect()(CCC);
const EEE = props => <DDD {...props} />;
const FFF = connect(state => state)(EEE);
ReactDOM.render(
<Provider store={store}>
<FFF />
</Provider>,
document.getElementById('root')
);
store.dispatch({ type: 'SHOW_FORM' })
store.dispatch({ type: 'HIDE_FORM' });
It appears #579 (fixed #577) also fixes this one.
Most helpful comment
I was able to repro the bug above. I refactored out redux-form and ended up with this:
It appears #579 (fixed #577) also fixes this one.