Recently I ran into this issue while working on React JS project where I was passing a part of parent component state to child component via props. Then I was using that prop to set the initial state of my child component (after doing some other calculations). So the problem was when the parent component re-renders on state change, the child component is not rendered with updated state value. For example —
// our child componentclass ChildComponent extends Component {constructor(){super(props);this.state = { count:this.props.value };}
render(){
return(
<div>
<p>I have {this.state.count} candies!</p>
</div>
);
}
}
// In parent component
// Assuming this.state.value = 5//This will render correctly "I have 5 candies!"<ChildComponent value = {this.state.value} />
// Now parent state "value" changed to 10// This time child will again render "I have 5 candies!"<ChildComponent value = {this.state.value} />
Well, the constructor of the component is executed only once, when the component is mounted. It will not get executed when component re-renders. When the parent component is re-rendered it will not destroy and recreate the child component. React will reuse the child component rendered earlier and do not run the constructor.
Since we are setting the state of child component only in the constructor which does not get called when child re-renders. So the state does not update even though child component is re-rendered upon receiving new props form parent component. That’s why the state “count” in child component still have “5” as a value.
From the official React documentation -
componentWillReceiveProps()
is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may comparethis.props
andnextProps
and perform state transitions usingthis.setState()
in this method
nextProps is the latest props received from the parent component.
We will use this life cycle method and update the state of child component when it receives new props from the parent. We will compare the current props value with the nextProps and if they are different then we will update the state of child component using setState() method.
class ChildComponent extends Component {
constructor(){ ... }
componentWillReceiveProps(nextProps){
if(nextProps.value !== this.props.value){
this.setState({count:nextProps.value});
}
}
render(){...}
}
All though this solutions works but React recommends a different approach you might want to look at. It’s called Lifting State Up.