This article is meant to be an easy to digest note to myself and fellow developers on good practices for how to avoid pointless re-renders.

Before we look into different APIs and techniques one needs to have a brief understanding about what re-renders are and how they can be problematic.

React achieves a fast and responsive UI by re-rendering components on every state change (using setState) or from changes of props, followed by React’s reconciliation diffing algorithm that diffs previous renders with current render output to determine if React should commit changes to the component tree (e.g. DOM) with the new updates.

However, unnecessary component re-renders will happen and can be expensive, It’s been a common performance pitfall in every single React project that I’ve been working on.

Alright, let’s move on.

Pure Components

Pure Components shallowly compares the old state & props with the new state & props. Always extend class components from React.PureComponent.

See example here

If you are like me and prefer the functional paradigm of React or your component does not need local state, then use the memo wrapper to protect functional components from re-rendering given the same input.

See example here

Should Component Update

Most likely Pure Components will be sufficient enough. However in cases of props or state structures with deeply nested objects, values won’t be compared and you are better off using the shouldComponentUpdate life-cycle method which is invoked on state or prop changes before render is called. Use this mechanism for granular control over when a component should re-render.

See example here

Inline Functions

Passing anonymous functions as props will cause the receiving component to re-render every time its parent re-renders because anonymous functions are re-initialized on every state or props change. Even if the function is still the same it will create a new memory reference since the function has to be re-allocated. Try lifting inline functions one level up from render if possible.

class App extends React.Component {

nameHandler = () => "foo" render() {

<Incorrect name={() => "foo"} />

<Correct name={this.nameHandler} />

}

}

Same principles applies to using bind in render. Remember to always bind your handlers in the constructor since Function.prototype.bind will create a new function on every invocation.

class App extends React.Component {

constructor(props) {

super(props)

this.correctHandler = this.correctHandler.bind(this)

} correctHandler() {

return "foo"

} incorrectHandler() {

return "foo"

} render() {

<Incorrect name={this.incorrectHandler.bind(this)} />

<Correct name={this.correctHandler} />

}

}

see example here

How Do I Even Track Rendering Of Components?

You can measure the rendering of a specific component simply by putting a console.log or console.count statement in the render method. If you have no clue where to start looking for potential unnecessary re-renders in your application then use the highlight updates feature in React DevTools. More on how to profile a React application can be found here and if you want to learn how to check the exact reason behind a certain re-render then it’s highlighted here.