useMemo - React Hooks Series

useMemo Banner

Welcome back to the series of React Hooks.

Series path

The main objective will be to explore how re-rendering works in React, why that is a critical factor for React applications, and how the useMemo hook can leverage it to build a performance boost in your applications. We will also see when useMemo can cause performance issues.

What is useMemo hook?

useMemo() is a built-in React hook that accepts two arguments — a function compute that computes a result and the dependencies array:

const memoizedResult = useMemo(compute, dependencies);

Let us try to get the essence of the useMemo hook. During the first rendering, useMemo(compute, dependencies) invokes the compute function, which is the first argument, memoizes the calculation result, and returns it to the component.

If during the next renderings the dependencies change, then useMemo() invokes compute, memoizes the new value, and returns it. But if dependencies don't change during re-rendering, then useMemo() doesn't invoke compute but returns the memoized value.

When to Use useMemo?

The basic and first step is to write the code first and then revisit it to see if any optimization can be made.

Implementing useMemo too often in an application can harm the performance.

When looking to implement useMemo, you can check with profiling tools in the debugger to identify any expensive performance issues. By expensive, I mean if the application is consuming a lot of resources (memory). It makes sense to memoize with useMemo only if you declare a large number of variables in a function at render.

Example

A component <ComputeFactorial /> calculates the factorial of a number introduced into an input field.

Here’s a possible implementation of <ComputeFactorial /> component:

import { useState } from "react";

export const ComputeFactorial = () => {
  const [number, setNumber] = useState(1);
  const [inc, setInc] = useState(0);

  const factorial = getFactorialOf(number);

  return (
    <div>
      Factorial of
      <input
        type="number"
        value={number}
        onChange={(event) => setNumber(Number(event.target.value))}
      />
      is {factorial}
      <button onClick={() => setInc((i) => i + 1)}>Force Re-render</button>
    </div>
  );
};

function getFactorialOf(n) {
  console.log("getFactorialOf(n) is called!");
  return n <= 0 ? 1 : n * getFactorialOf(n - 1);
}

Every time the input value is changed, the factorial is calculated usinggetFactorialOf(n) and 'getFactorialOf(n) is called!' is logged to console.

On the other hand, each time you click the Force Re-render button, the inc state value is updated. Updating the inc state value triggers <ComputeFactorial /> component to re-render. When a component is re-rendered, the factorial is recalculated again — 'getFactorialOf(n) is called!' is logged to console.

How can you memoize the factorial calculation when the component re-renders? Welcome useMemo() hook!

By using useMemo(() => getFactorialOf(number), [number]) instead of simple getFactorialOf(number), React memoizes the factorial calculation.

Let’s improve <ComputeFactorial /> and memoize the factorial calculation:

import { useState, useMemo } from "react";

export const ComputeFactorial = () => {
  const [number, setNumber] = useState(1);
  const [inc, setInc] = useState(0);

  const factorial = useMemo(() => getFactorialOf(number), [number]);

  return (
    <div>
      Factorial of
      <input
        type="number"
        value={number}
        onChange={(event) => setNumber(Number(event.target.value))}
      />
      is {factorial}
      <button onClick={() => setInc((i) => i + 1)}>Force Re-render</button>
    </div>
  );
};

function getFactorialOf(n) {
  console.log("getFactorialOf(n) is called!");
  return n <= 0 ? 1 : n * getFactorialOf(n - 1);
}

Every time the value of the number is changed, 'getFactorialOf(n) called!' is logged to console, which is expected.

However, if you click Force Re-render button, 'getFactorialOf(n) is called!' isn’t logged to console because useMemo(() => getFactorialOf(number), [number]) returns the memoized factorial calculation. How cool is that!

Wrapping up

This article explored the useMemo hook and when it is appropriate to use it in a React application.

We also see that useMemo helps in boosting the performance of an application by "remembering" or memoizing expensive functions and preventing a re-render every time there is a change in the application.

We also learnt that while using useMemo can improve the application's performance, overusing useMemo can slow down your application. This means the more useMemo hook is used, and the memory has to be allocated for the memory.

If you have any questions, suggestions, corrections, I will look forward to it. Thank you for making it this far.

Series path

💌 If you'd like to receive more tutorials in your inbox, you can sign up for the newsletter here.

Discussions

Up next