×

Avoiding Expensive Recalculation in React With the useMemo Hook

Sagiv Ramrajkar
Sagiv Ramrajkar

Monday, March 13th, 2023

Read Time
4 min read

Exploring the power of React Hooks through the lens of the common expensive recalculation problem

Exploring the power of React Hooks
Photo by FRANCESCOCH/GETTY IMAGES

One of my first tasks as a React developer was to show a banner in a specific time range. After the first run of developing it, I found that the component which renders the banner is running the calculation for the time range multiple times. This was the first time I met this issue, but it turned out to be a very common problem for React developers. In this blog post, I’ll share how I resolved it using the useMemo hook.

Problem: Inefficient Recalculation

The main cause of inefficient recalculation is unnecessary re-calculation. A re-calculate is unnecessary when the component’s props and state have not changed but the calculation is still computed. This can happen, for example, when a parent component re-renders and passes the same props value for to a child component, and the child component calls the calculation method even though it’s the same input.

Inefficient Recalculation
Photo by Maurits Cornelis Escher

Debug: React Developer Tools Profiler Is Here!

After finishing creating the component, I was asked by the code reviewer to check the calculate method that it didn’t causing performance issues. To do it, I used React Developer Tools Profiler.

When you have the React Developer Tools installed, open the developer console and go to the “React” or “Components” tab. From there, click the “Profiler” button to open the Profiler panel. To start recording component performance, click the “Record” button and interact with your app to trigger updates to your React components. Then, click the “Stop” button to stop recording. You can then inspect the recorded performance data to identify which components are causing performance issues in your application. The performance profile will show you a breakdown of the time spent rendering each component, as well as information on how many times each component is rendered. Once you’ve identified the problem, you can make necessary changes to optimize the component performance and re-test to see if the issue is resolved

Indeed, using this tool I found that the new component I added had a high time spent when the component re-rendered, so I started investigating how to fix it.

One of React core features is the ability for components to re-render in response to changes in their props or state. However, when a component re-renders, it can cause a cascading effect where child components also re-render, leading to poor performance, unintended side effects, inconsistencies in the UI, and unnecessary re-renders. This is known as the problem of multiple renderings.

React Developer Tools Profiler
Photo by Addy Osmani

Solution: useMemo Hook for the Rescue!

While searching for how to solve this issue, the most common solution is to use the useMemo hook.

React Hooks are functions that allow you to add state and other React features to functional components. Hooks let you “hook into” React state and lifecycle features from functional components. Hooks let you reuse stateful logic across components without writing a class.

The useMemo hook is a way to optimize the performance of your React application by only re-computing a value when one of its dependencies has changed. It is particularly useful for preventing unnecessary re-renders in functional components.

Here’s an example of how you can use useMemo to fix the problem of expensive recalculation in a component by setting data as a dependency for filteredData:

import React, { useMemo } from 'react';

function MyComponent({ someProp }) {
  // Define an expensive calculation
  const expensiveCalculation = (someProp) => {
    // ... Some expensive calculation that depends on the value of someProp
    return result;
  }

  // Use useMemo to memoize the expensive calculation
  const memoizedValue = useMemo(() => expensiveCalculation(someProp), [someProp]);

  return (
    <div>
      {/* Render the memoized value */}
      {memoizedValue}
    </div>
  );
}

In this example, the MyComponent function takes a someProp prop and performs an expensive calculation based on its value. By using the useMemo hook, we can memoize the expensive calculation so that it is only performed when the value of someProp changes.

It is possible to specify more than one dependency. In this case, the value will be re-calculated if one of the dependencies is changed. For this reason, the dependencies array should be kept as small as possible.

The useMemo hook can also be used to memoize expensive calculations such as sorting, filtering, or mapping large data sets.

In my case, I used a boolean function as a dependency for useMemo. The function indicates whether the specific banner should be displayed or not. Only when this state is changed will the component be re-rendered.

useMemo Hook for the Rescue

Conclusion

useMemo is a powerful tool in React for avoiding unnecessary re-calculations. It allows you to memoize values computed based on props or state and can be particularly useful for handling large data sets or expensive calculations. Using useMemo in your React component can effectively optimize your application’s performance.