componentWillReceiveProps not being called even though mapStateToProps returns different value
See original GitHub issueI had initially posted this issue on the redux github here(https://github.com/reactjs/redux/issues/2317) but was advised to move it here.
Do you want to request a feature or report a bug?
bug
What is the current behavior? componentWillReceiveProps is not called even though mapStateToProps returns different values
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.
It’d be hard to create a minimal example here but I can show what’s happening in my code. I’m having problems getting componentWillReceiveProps
to be called reliably in my code. The logging output below is writing out the calls to mapStateToProps
, componentWillReceiveProps
, and render
and as you can see the final call that I would expect to happen isn’t happening even though mapStateToProps
is returning state that would be different when using shallow compare.
Console Logging
detailsTabContainer.mapStateToProps {"drawerClosed":true}
detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
detailsTabContainer.js:3(2) detailsTabContainer.componentWillReceiveProps (isClosing, isSubmitting) false true
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
detailsTabContainer.js:57 detailsTabContainer.render
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
detailsTabContainer.js:3(2) detailsTabContainer.componentWillReceiveProps (isClosing, isSubmitting) false true
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
detailsTabContainer.js:57 detailsTabContainer.render
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(4) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(4) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":false}
code
import React from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {submit} from 'redux-form';
import { CANVAS_OBJECT_TYPES } from '../../../../../constants/canvasObjectTypes';
import * as icActions from '../../../../../state/actions/internalControl.action';
import DetailsTab from './detailsTab';
class DetailsTabContainer extends React.Component {
//This is a hack. Should be done with a callback from the flyout after the flyout is fully open.
componentDidMount() {
console.log('detailsTabContainer.componentDidMount');
if (this.props.content.isNew) {
setTimeout(() => {
this.refs && this.refs.controlId && this.refs.controlId.focus();
}, 200);
}
}
componentWillReceiveProps(nextProps) {
const isClosing = this.props.drawerClosed && nextProps.drawerClosed === false;
const isSubmitting = !this.props.drawerSubmitted && nextProps.drawerSubmitted === true;
console.log('detailsTabContainer.componentWillReceiveProps (isClosing, isSubmitting)', isClosing, isSubmitting);
if (isClosing || isSubmitting) {
this.props.actions.submit(CANVAS_OBJECT_TYPES.Control);
}
}
render() {
console.log('detailsTabContainer.render');
// TODO: Ryan - remove spreading out of props and moved to more typed approach
return <DetailsTab {...this.props}/>;
}
}
const mapStateToProps = state => {
const props = {
drawerClosed: state.drawerState && state.drawerState.drawer && state.drawerState.drawer.show,
drawerSubmitted:(state.drawerState && state.drawerState.drawer && state.drawerState.drawer.submitted) || false
};
console.log('detailsTabContainer.mapStateToProps', JSON.stringify(props));
return props;
};
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators({submit}, dispatch)
})
export default connect(mapStateToProps, mapDispatchToProps)(DetailsTabContainer);
What is the expected behavior? That componentWillReceiveProps would be called after the last two calls to mapStateToProps as the result is different.
(2) detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":true,"drawerSubmitted":true}
detailsTabContainer.js:69 detailsTabContainer.mapStateToProps {"drawerClosed":false}
Which versions of Redux, and which browser and OS are affected by this issue? Did this work in previous versions of Redux?
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-redux": "^5.0.3",
"redux": "^3.6.0",
chrome Version 57.0.2987.110 (64-bit) mac seirra 10.12.3
Haven’t tried it in previous versions of Redux
Issue Analytics
- State:
- Created 6 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
Hi there, what does “accidental mutation” mean? I am having a situation where componentWillReceiveProps is not been triggered even though the properties are changing.
Oh that, yeah. No, I create a new state. Ive been using this stack a few times, with not too much trouble lately. My problem is not a lack of rendering (the render method is called), but that the props-receive hook for updating internal state is not called. If time permits I’ll try to produce a repro tomorrow.