DEV Community

Kento Honda
Kento Honda

Posted on

Usage of useMemo hook in React

Intro

Throughout my experience working on various projects at my current company, I have gained a wealth of knowledge about React.js, which is undoubtedly one of the most popular JavaScript frameworks used for front-end development nowadays.

Many programming learners, like myself, have already delved into learning React.js, especially those aspiring to become front-end developers.

However, I have noticed that the useMemo hook is not always utilized as much as the useState or useEffect hooks in web development, although it does depend on the specific project requirements.

Therefore, I have decided to write an article introducing the basic usage of the useMemo hook, a built-in React hook, for those who may not be familiar with it.

What is useMemo hook in React.js

useMemo is a React hook memorizing the result of a function call (returned value from a function). And this memorization is helpful for optimizing the performance of web applications.

useMemo wraps a function in it and that function is not triggered until the value defined at dependencies of useMemo has been changed.

In other words, useMemo computes only when one of its dependencies is updated in order to avoid unnecessary calculations.

How useMemo works

To demonstrate the mechanism of useMemo hook, here is a sample code snippet;

// Child component

import { useMemo } from "react";

const Child = ({ a:number, b:number }) => {
  // Callback function returning the sum of a and b
  const sum = useMemo(() => {
    // Check if Child component is rendered
    console.log("Child component is rendered");
    return a + b;
  // array of dependencies ([a,b])
  }, [a, b]);
  return <div>No. {sum}</div>;
};

export default Child;
Enter fullscreen mode Exit fullscreen mode

As you can see, there are two React function components whose names are Parent and Child. In the Child component, useMemo is used and has the following two arguments;

  • Callback function that returns the sum of two parameters ('a' and 'b')
  • Array of dependencies ([a,b]) that specify when useMemo should be fired

Now that we have these two arguments in useMemo, it is possible to memorize the value returned from the callback function until one of the value dependencies defined in useMemo has been changed.

As a result, thanks to the effects of useMemo hook, we could optimize performances in our React applications.

Let's compare the cases with and without useMemo hook

In the previous section, we could briefly learn the basics of how useMemo hook works. So let's dive into a little deeper side of useMemo hook to understand more about the benefit of using it.

Here is another code snippet with a component whose name is Parent component, containing the Child component.


// Parent Component

import Child from "./Child";
import { useState } from "react";

const Parent = () => {
  // Declare React state for the counter
  const [count, setCount] = useState(0);

  // Define two constant variables that have numbers respectively
  const numA = 3;
  const numB = 40;

  // A function that is triggered by onClick event in button component and increment the number of counter by 1
  const handleAddCount = () => {
    setCount((prevState) => prevState + 1);
  };

  // Check if Parent component is rendered
  console.log("Parent component is rendered");

  return (
    <>
      <div style={{ paddingTop: "2rem" }}>
        <p>Number in Child component</p>
        {/* Pass two variables (numA and numB) as props to the Child component */}
        <Child a={numA} b={numB} />
      </div>
      <div style={{ paddingTop: "4rem" }}>
        <p>Count number: {count} counts</p>
        {/* Set onClick event to increment the counter by 1 */}
        <button onClick={handleAddCount}>ADD</button>
      </div>
    </>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode

In the Parent component, there is a counter implemented by counter state and setCounter function with React state. So every time I click the "ADD" button, the number of counter displayed will be incremented by 1.

Case1: With useMemo hook

And the Child component in Parent component is the same component that is defined above.

// Child component (with useMemo)

import { useMemo } from "react";

const Child = ({ a:number, b:number }) => {
  // Callback function returning the sum of a and b
  const sum = useMemo(() => {
    // Check if Child component is rendered
    console.log("Child component is rendered");
    return a + b;
  // array of dependencies ([a,b])
  }, [a, b]);
  return <div>No. {sum}</div>;
};

export default Child;
Enter fullscreen mode Exit fullscreen mode

So now, let's say I click the ADD button in the Parent component, and what will happen in the console?

As you can see the screenshot below, the counter is incremented to 5. At the same time, thanks to the effect of useMemo hook, even though every time the ADD button is clicked (to update the React state of counter in the Parent component), only the Parent component is rendered. (Child component is not re-rendered at all).

Image description

Case2: Without useMemo hook

Now that we could make sure the advantage of using useMemo hook to avoid re-rendering in Child component.

So what if I modify the portion of codes in Child component and remove useMemo hook in it, what will happen?

If the useMemo hook is removed in Child component, it would look like this;

// Child component (without useMemo hook)

const Child = ({ a:number, b:number }) => {
  const sum = a + b;
  // Check if Child component is rendered
  console.log("Child component is rendered");
  return <div>No. {sum}</div>;
};

export default Child;
Enter fullscreen mode Exit fullscreen mode

And then, when I did the same thing in Case1 (Clicking the ADD button in parent component), the result of console is in this screenshot.

Image description

Now it turned out that without useMemo hook in Child component, Child component is always re-rendered when the counter state in Parent component is updated.

Considering better performances in React applications, it is sure that we should utilize useMemo hook effectively.

Conclusion

The useMemo hook plays a crucial role in optimizing React applications by memorizing values and preventing unnecessary renderings.

As a Front-End Developer specializing in React.js, effectively utilizing the useMemo hook has helped me advance my skills. I plan to explore it further and integrate it into my personal projects during refactoring.

Additionally, there is another React hook, useCallback, which serves a similar purpose. In the near future, I intend to write an article summarizing the basic usage of the useCallback hook as well.

Top comments (2)

Collapse
 
lukashenkor profile image
RAMAN LUKASHENKA

Hi @keento0809! Thanks for your article.
I just wanted to add that with this approach of using useMemo hook your Child component will be re-rendered any time your parent component is re-rendered. The useMemo hook in this particular situation will only help us to avoid sum recalculations, but if we add console.log in the body of the Child component (outside of the useMemo hook) we'll see in the console that every time we increase Parent's count state our Child's log function runs
So what I usually do to avoid unnecessary re-renders is wrapping child component with React built-in memo() function. It'll prevent child re-renders when it's props are the same. Notice that if you pass arrays or objects to Child component you'll have to pass additional argument to memo() function: arePropsEqual(prev, next) function. This function accepts two arguments: component's previous props and it's next props. And you can manually specify checking props function

Collapse
 
keento0809 profile image
Kento Honda

@lukashenkor Thank you for giving me very informative tips! I'll implement what you usually do for avoiding unnecessary re-renders on the comment, and fix the contents of this article later on:)