IMPROVING PERFORMANCE IN REACT APP

Aditya Jain
4 min readMay 20, 2022

Optimizing application performance is key for developers who are mindful of keeping a user’s experience positive to keep them on an app and engaged.

According to research by Akamai, a second delay in load time can cause a 7 percent reduction in conversions, making it imperative for developers to create apps with optimized performance.

In React applications, we are guaranteed a very fast UI by default. However, as an application grows, developers may encounter some performance issues.

In this guide, we will discuss five important ways to optimize the performance of a React application, including pre-optimization techniques. These include:

React pre-optimization techniques

Before optimizing a React application, we must understand how React updates its UI and how to measure an app’s performance. This makes it easy to solve any React performance problems.

Let’s start by reviewing how the React UI updates.

Understanding how React updates its UI

When we create a rendered component, React creates a virtual DOM for its element tree in the component. Now, whenever the state of the component changes, React recreates the virtual DOM tree and compares the result with the previous render.

It then only updates the changed element in the actual DOM. This process is called diffing.

React uses the concept of a virtual DOM to minimize the performance cost of re-rendering a webpage because the actual DOM is expensive to manipulate.

This is great because it speeds up the UI render time. However, this concept can also slow down a complex app if it’s not managed very well.

What we can deduce here is that a state change in a React component causes a re-render. Likewise, when the state passes down to a child component as a prop, it re-renders the child and so on, which is fine because React must update the UI.

The issue comes when the child components are not affected by the state change. In other words, they do not receive any prop from the parent component.

React nonetheless re-renders these child components. So, as long as the parent component re-renders, all of its child components re-render regardless of whether a prop passes to them or not; this is the default behavior of React.

Profiling the React app to understand where bottlenecks are

React allows us to measure the performance of our apps using the Profiler in the React DevTools. There, we can gather performance information every time our application renders.

The profiler records how long it takes a component to render, why a component is rendering, and more. From there, we can investigate the affected component and provide the necessary optimization.

Use the Production Build

If you’re benchmarking or experiencing performance problems in your React apps, make sure you’re testing with the minified production build.

By default, React includes many helpful warnings. These warnings are very useful in development. However, they make React larger and slower so you should make sure to use the production version when you deploy the app.

If you aren’t sure whether your build process is set up correctly, you can check it by installing React Developer Tools for Chrome.

Virtualize Long Lists

If your application renders long lists of data (hundreds or thousands of rows), we recommend using a technique known as “windowing”. This technique only renders a small subset of your rows at any given time, and can dramatically reduce the time it takes to re-render the components as well as the number of DOM nodes created.

react-window and react-virtualized are popular windowing libraries. They provide several reusable components for displaying lists, grids, and tabular data. You can also create your own windowing component, like Twitter did, if you want something more tailored to your application’s specific use case.

Avoid Reconciliation

React builds and maintains an internal representation of the rendered UI. It includes the React elements you return from your components. This representation lets React avoid creating DOM nodes and accessing existing ones beyond necessity, as that can be slower than operations on JavaScript objects. Sometimes it is referred to as a “virtual DOM”, but it works the same way on React Native.

When a component’s props or state change, React decides whether an actual DOM update is necessary by comparing the newly returned element with the previously rendered one. When they are not equal, React will update the DOM.

Even though React only updates the changed DOM nodes, re-rendering still takes some time. In many cases it’s not a problem, but if the slowdown is noticeable, you can speed all of this up by overriding the lifecycle function shouldComponentUpdate, which is triggered before the re-rendering process starts. The default implementation of this function returns true, leaving React to perform the update:

shouldComponentUpdate(nextProps, nextState) {
return true;
}

If you know that in some situations your component doesn’t need to update, you can return false from shouldComponentUpdate instead, to skip the whole rendering process, including calling render() on this component and below.

In most cases, instead of writing shouldComponentUpdate() by hand, you can inherit from React.PureComponent. It is equivalent to implementing shouldComponentUpdate() with a shallow comparison of current and previous props and state.

Use React.Fragment to Avoid Adding Extra Nodes to the DOM

When working with React, there are cases where you will need to render multiple elements or return a group of related items.

Wrapping up

The techniques outlined above are all great ways for you to take into practice optimizing performance for your application.

Thank You

--

--