Emad Emami
Emad Emami

Reputation: 6629

shouldComponentUpdate implementation in React PureComponent

I'm using PureComponent for better performance in my React application and it has props but I don't want it to run render method when this props changed. I know we can not use shouldComponentUpdate in React.PureComponent but my question is:

Is there any way to avoid updating React.PureComponent?

I want this component don't update/render at all.

Edit : I'm getting this warning when using shouldComponentUpdate in pureComponent:

Warning: GameObjectFall has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.

Upvotes: 5

Views: 15946

Answers (3)

Shubham Khatri
Shubham Khatri

Reputation: 281686

PureComponent changes the life-cycle method shouldComponentUpdate and adds some logic to automatically check whether a re-render is required for the component. This allows a PureComponent to call method render only if it detects changes in state or props, hence, one can change the state in many components without having to write extra checks.

However you can additionally use the proven method shouldComponentUpdate to manually determine the necessity of a new re-render.

It doesn't override the PureComponent logic but adds any other things that you added in the custom implementation of shouldComponentUpdate

As of v16.9.0, React throws the following warning

Warning: shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.

See a snippet which illustrates this

class App extends React.Component {
  state = {
    count1: 0,
    count2: 0,
    count3: 0
  }
  
  increment = (key) => {
     this.setState(prevState => ({[key]: prevState[key] + 1}))
  }
  
  render() {
    console.log('render parent');
    return (
      <div>
         {this.state.count1}
         <Child count={this.state.count1} countNew={this.state.count3}/>
         <button onClick={() => this.increment('count1')}>IncrementOne</button>
         <button onClick={() => this.increment('count2')}>IncrementTwo</button>
      </div>
    )
  }
}

class Child extends React.Component {
   shouldComponentUpdate(nextProps, nextState) {
      console.log('scu');
      if (nextProps.count !== this.props.count) {
        return false;
      }
   }
   render() {
       console.log('render child');
      return (
        <div>Child: {this.props.count}</div>
      )
   }
}
ReactDOM.render(<App/>, 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"/>

Upvotes: 6

omri_saadon
omri_saadon

Reputation: 10631

When using PureComponent, there is an implementation to the method shouldComponentUpdate which does only a shallow comparison. You should use it when your props are Boolean, string or any other primitive type.

You can implement your implementation to shouldComponentUpdate which will override the default shallow comparison.

When I say shallow comparison I mean that if you were compare between objects/arrays, you would get wrong comparison. For example:

const first = { key: 'value' };
const second = { key: 'value' };
if (first === second) {
    // You won't get here
}

Upvotes: 0

Sajith Edirisinghe
Sajith Edirisinghe

Reputation: 1727

According to PureComponent Documentation it only does a shallow comparison in shouldComponentUpdate(). Hence, if all your props are wrapped in an object and if you mutate the properties within that object, component will not re-render since shallow comparison will always result in true.

As an example assume propContainer = {name: "John", age: "20"} and this.props.container = propContainer, then mutation within propContainer object (changing name, age values) will not re-render the component.

Upvotes: 2

Related Questions