Dealing with performance issues

Tools

To analyze this, I used mainly Chrome DevTools and React Developer Tools. They’re really powerful tools and of great help in debugging.

One really useful feature of this tool is that it enables you to highlight which components are updated. To turn it on, open Chrome DevTools, go to the React tab, and click on the checkbox “Highlight Updates”

Chrome DevTools screenshot

Derived Data

To reproduce the issue we were facing, I’ve forked a CodeSandbox (original) that implements the Todo List example from redux docs and made some changes to it:

Show menu is a button that toggles the Todo Filters. Changed the getVisibleTodos function on todos.js to use filter method.

Here is the CodeSandbox.

The blue rectangles are highlighting the updated components.

Whenever the button for opening/closing the menu is clicked, the todo list is also updated, even though an unrelated value was changed! Well, our application had a really long list (lots of DOM nodes) that was constantly re-rendering on every interaction making everything slower. So…

Why is this happening?

This part of the code is the culprit:

This is the butler.

What happens is every time the mapStateToProps function is called, the function getVisibleTodos returns a new array and this makes TodoList re-render because:

To change this behaviour, you’d have to either change mapStateToProps or the component’s shouldComponentUpdate() .

Changing the shouldComponentUpdate() would depend on the data and component being optimized, and that could mean scalability problems (should we optimize every new React component according to the screen? what about reusability?), so we put this solution on hold.

The other option, to improve mapStateToProps is actually the recommended approach. I’ve modified the previous sandbox to use reselect and we can see that the list doesn’t update anymore when the menu button is clicked! (Link)

New sandbox using reselect

What does reselect do? It is a memoized selector, meaning it caches the result given the inputs and return the same value/reference, meaning the strict equality ( === ) returns true .

Disclaimer: This is the example from reselect ’s motivation.

Arrow functions

Yes, inline arrow functions can be problematic. An arrow function has the same problem as computing derived data: a new function is passed in every render. This may cause unnecessary re-renders.

From React official documentation:

Using an arrow function in render creates a new function each time the component renders, which may have performance implications (see below).

More on this topic

Pure components

PureComponent performs a shallow comparison of props and state, and reduces the chance that you’ll skip a necessary update. (From React Docs)

PureComponent implements the shouldComponentUpdate lifecycle.

shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true .

i.e., when you use Component your components re-renders every props or state change, regardless of the change.

Virtualization

Also, another possible solution that could have been applied in our case (which we didn’t for reasons particular to our design) was using react-virtualized , what it does is rendering only what’s visible on the screen.

This is really useful when you have large lists of images and you don’t want the user to load all of them before they are actually on screen.

Non react issues

We also had some issues unrelated to React that affected performance: