Gabriel
Gabriel

Reputation: 459

Why setState from parent component calling child componentDidUpdate?

In this example componentDidUpdate fired when I set state trail. HelloMessage props and state not changed so why this method is calling? How to prevent this?

class HelloMessage extends React.Component {
  componentDidUpdate(prevProps, prevState) {
    console.log('HelloMessage did update');
  }

  render() {
    return <div>Hellooo</div>;
  }
}

class App extends React.Component {
  state = { trail: null }

  componentDidMount() {
    this.setState({ trail: 'First' });    
  }

  render() {
    return (
      <div>
        <HelloMessage />
        <div>
          {this.state.trail}
        </div>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('container')
);

Upvotes: 1

Views: 1008

Answers (5)

Bhojendra Rauniyar
Bhojendra Rauniyar

Reputation: 85545

It's expected behavior. Whenever the parent component's states changes the component will be re-rendered. And all of your components logic ie. child component also exists inside render method. So, the child component is rendered again.

If you do not want the updates, then you need to return react's shouldComponentUpdate hook explicitly.

shouldComponentUpdate(nextProps, nextState) {
    return nextState
}

Since nextState of the child component is still null shouldComponentUpdate will return null. This inform not to update the component. This will allow the child component to be re-rendered only when child's state gets changes.

Upvotes: 1

Thien
Thien

Reputation: 31

componentDidMount() {
  this.setState({ trail: 'First' });    
}

This state change will invoke rerender the App, which will trigger update on child HelloMessage component. To avoid this, use shouldComponentUpdate(nextProps, nextState) in HelloMessage and compare nextProps with its current props to decide whether to update the component.

Upvotes: 0

bamse
bamse

Reputation: 4373

Since HelloMessage doesn't get any props it could extend React.PureComponent. You'll get the same result as using shouldComponentUpdate to return false.

Upvotes: 2

Jayce444
Jayce444

Reputation: 9063

I believe the logic behind this is such:

If a component's props or state change, then it trigger's a re-render. This also means that it will re-render its children (and so on down the tree). Now, even though the props/state in the child haven't changed, it will still trigger a re-render because shouldComponentUpdate() always returns true by default. So if you don't want the child to re-render, even if its parent re-renders, then you can add:

shouldComponentUpdate() {
    return false;
}

So that it doesn't update (obviously you can add checks in that lifecycle method to decide whether to update, should you add props later on and such).

Upvotes: 0

Jitesh Manglani
Jitesh Manglani

Reputation: 485

It will call componentDidUpdate because parent component's render method is called. You can check if props have changed then execute the code.

Upvotes: 0

Related Questions