Avoid unnecessary Rendering With ShouldComponentUpdate

When updates happen, React virtual DOM can determine the changes by diffing the original DOM with the re-computed one. React does wonders by maintaining a virtual DOM representation to avoid expensive DOM operations.

The maintenance of that virtual DOM can also be expensive. Imagine a very large, complicated render tree. If you update the props of any node, React needs to recompute the render tree from that node all the way down to the leaves, where it finally does its virtual DOM comparisons.

Fortunately, React provides a mechanism for avoiding this, namely shouldComponentUpdate

By default

shouldComponentUpdate(nextProps, nextState) {

return true;

}

shouldComponetUpdate( ) — return false from this method, and the component’s entire subtree does not bother re-rendering. We just need to figure out how/when to return false.

PureComponent

The simplest way to take advantage of this is to keep your render methods pure — your component should render only based on state and props.

class Foo extends React.PureComponent {

render() {

return (

<div>

Hello!

</div>

);

}

}

Most of the time, you can use React.PureComponent instead of writing your own shouldComponentUpdate . By default it does a shallow comparison like

shouldComponentUpdate(nextProps, nextState) {

return !shallowEqual(this.props, nextProps) ||

!shallowEqual(this.state, nextState);

}

If no changes in props/state are detected, it doesn’t re-render.

Avoid Function.bind() / Inline (Anonymous) functions

Bind the function in render method is not good way because, a bind call or arrow function in a JSX prop will create a new function on every single render.

class Foo extends React.Component {

render() {

return (

<div onClick={this._onClick.bind(this)}>

Hello!

</div>

);

}

_onClick() {

// Do whatever we like, referencing "this" as appropriate

}

}

Instead of bind a function in render method we can bind the function in constructor because of that only single function is created.

class Foo extends React.Component {

constructor() {

super();

this._onClick = this._onClick.bind(this);

}

render() {

return (

<div onClick={this._onClick}>

Hello!

</div>

);

}

_onClick() {

// Do whatever we like, referencing "this" as appropriate

}

}

Set NODE_ENV to Production

React has great developer warnings and error checking, but these are only intended for development. If we take a look at React’s source code, we will see a lot of if (process.env.NODE_ENV === 'production') checks. This is running extra code that is not needed by the end user, calling this process.env.NODE_ENV is extremely slow.

For production environments, we can replace all instances of process.env.NODE_ENV with 'production’ or we can use envify node- module. envify will replace your environment variable checks with ordinary strings only the variables we use will be included.

After running it through envify with NODE_ENV set to production

if( "production" === "production") {

//envify

//uglify

//Do whatever we like

}

By running this through a good minifier (e.g. uglify), the above code would be stripped out completely.

UglifyJs will remove unreachable code and warn about it, apart from that it can perform various small optimizations like shorten variable names, join consecutive var declarations and if-else statements etc UglifyJs

Just keep in mind that we don’t want to do this in development because it will remove all those helpful developer warnings.

Don’t use array indexes as keys

So many times we use the index of an item as its key when they render in a list.

{todos.map((todo, index) =>

<Todo

{...todo}

key={index}

/>

)}

a key is the only thing React uses to identify DOM elements. What happens if you push an item to the list or remove something in the middle? If the key is same as before React assumes that the DOM element represents the same component as before. But that is no longer true.

e.g. the first item in the todo list is completed and the second one is not. Then the second todo would have key set to ‘0’ and React would think that the first todo changed, looses the track of identity. If the key was set to id it would just remove the first todo from the DOM.

Better Way

{todos.map((todo) =>

<Todo {...todo}

key={todo.id} />

)}

Render lists in dedicated components

React is notoriously bad at rendering large collections as the reconciler has to evaluate the components produced by a collection on each collection change. It is therefore recommended to have components that just map over a collection and render it, and render nothing else:

class MyComponent extends Component {

render() {

const {todos, user} = this.props;

return (<div>

{user.name}

<ul>

{todos.map(todo => <TodoView todo={todo} key={todo.id}/>)}

</ul>

</div>)

}

}

In the above listing React will unnecessarily need to reconcile all TodoView components when the user.name changes. They won't re-render, but the reconcile process is expensive in itself.

Better Way

class MyComponent extends Component {

render() {

const {todos, user} = this.props;

return (<div>

{user.name}

<TodosView todos={todos} />

</div>)

}

} class TodosView extends Component {

render() {

const {todos} = this.props;

return <ul>

{todos.map(todo => <TodoView todo={todo} key={todo.id}/>)}

</ul>)

}

}

Profiling of React Components

React is usually quite fast out of the box. it’s quite common to find areas of your app which are slow, especially when we try to input data or scroll. If you have a list with hundreds of items then this can cause a lot of slowdown.

Profiling will show you which components in your app are being recalculated unnecessarily and which gives you a good starting point to speeding things up.

In the development mode, you can visualize how components mount, update, and unmount, using the performance tools in supported browsers. For example:

To do this in Chrome:

Temporarily disable all Chrome extensions, especially React DevTools. They can significantly skew the results! Make sure you’re running the application in the development mode. Open the Chrome DevTools Performance tab and press Record. Perform the actions you want to profile. Don’t record more than 20 seconds or Chrome might hang. Stop recording. React events will be grouped under the User Timing label.

If your Using React 15 you can achieve same thing with React-addons-perf tool.

We’ll start by installing React’s performance tools.

npm install --save-dev react-addons-perf

And then we can import it in our App.js:

import Perf from 'react-addons-perf'

window.Perf = Perf;

There are four Perf functions that we care about: