Reputation: 3964
The code below works nicely in my app. It seems like an anti-pattern though:
componentWillReceiveProps(nextProps) {
if (nextProps.conversation.length > this.props.conversation.length){
if (this.state.hideDiv) {
this.setState({
hideDiv: false,
});
}
this.props.incrementNotificationCount();
}
}
Explanation:
componentWillReceiveProps
checks if nextProps
conversation array is larger than this.props
coversation array. Meaning: I received a new conversation message.
If I did receive a new message, I want to show a div only if it is hidden, In this
component I have local state of hideDiv
.
If hidden:
if (this.state.hideDiv)
Show it:
this.setState({
hideDiv: false,
}).
Also, if I did receive a new message, I want to increment the notification count which is in a parent component
:
this.props.incrementNotificationCount()
This method causes the notification state
to be changed in the parent component
.
Question:
I know setting local state
in componentWillReceiveProps
will not cause a rerender
. But what happens if I set the state
of a parent component
in componentWillReceiveProps
?
And is this code an "anti-pattern"?
Upvotes: 0
Views: 1303
Reputation: 282130
Whenever the parent component rerenders, componentWillReceiveProps
in child is called before the child render function is called. In this function if you call setState
for the childComponent
, the next state is updated in the componentWillUpdate
function and then received by the render in the child.
Also when you call the parent function in the componentWillReceiveProps
which updates the parent state, the parent is rerendered
and thus the child rerenders again.
See a sample snippet which demostrates the same behaviour
class Parent extends React.Component {
state = {
childState: 1,
mystate: 2,
}
changeState = () => {
console.log('change state in parent called');
this.setState((prevState) => ({
mystate: prevState.mystate + 1
}))
}
componentWillUpdate(nextProps, nextState) {
console.log('cwu parent', nextState);
}
changeChildState = () => {
console.log('change child state called');
this.setState((prevState) => ({
childState: prevState.childState + 1
})
)
}
render() {
console.log('Parent rerender called');
return (
<div>
<div> Parent {this.state.mystate}</div>
<button onClick={() => this.changeChildState()}>Click</button>
<MyComponent val={this.state.childState} changeState={this.changeState}/>
</div>
)
}
}
class MyComponent extends React.Component {
state = {
someChildState: 1
}
componentWillReceiveProps(nextProps) {
if(nextProps.val !== this.props.val) {
console.log('child cwrp called');
this.setState((prevState) => ({someChildState: prevState.someChildState + 1}));
this.props.changeState();
}
}
componentWillUpdate(nextProps, nextState) {
console.log(nextState)
}
render() {
console.log('child render called')
return <div > {this.props.val} {this.state.someChildState} </div>
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Upvotes: 1