Hello Sunil
react-usememo-hook-feature-image

useMemo Hook : Performance Optimization Hook For React App ⚡️⚡️

From time to time React components have to perform expensive calculations. For example, given a big list of employees and a search query, the component should filter the employees’ names by the query.

In such cases, with care, you can try to improve the performance of your components using the memoization technique.

In this post, we are going to describe how and when to use the useMemo React hook.

What is useMemo Hook?

The useMemo hook is used to return a cached value in order to save any re-computation overhead.

It works by caching the output in the computer’s memory and then returning it whenever the same input is provided again.

The basic purpose of useMemo hook is related to the fact that we try to avoid the unnecessary re-rendering of components and props in our program.

So we make sure that only those components are re-rendered which witness a change in their values otherwise no need to re-render the component and slow down the performance.

This will make our program efficient and improves the overall performance of our React app.

So, there are two problems that useMemo hook seeks to address:

  • Referential equality
  • Computationally expensive operations

🤔 What is memoization?

The useMemo hook used in react which returns a memoized value.

In programming, memoization is an optimization technique that makes applications more efficient and hence faster.

It does this by storing computation results in cache, and retrieving that same information from the cache the next time it’s needed instead of computing it again.

Memoization is a simple but powerful trick that can help speed up our code, especially when dealing with repetitive and heavy computing functions.

For example, if there is a function to add two numbers, and we give the parameter as 1 and 2 for the first time the function will add these two numbers and return 3.

But if the same inputs come again then we will return the cached value i.e 3 and not compute with the add function again.

In react also, we use this concept, whenever in the React component, the state and props do not change the component and the component does not re-render, it shows the same output.

The useMemo hook is used to improve performance in our React application.

Syntax of useMemo Hook

useMemo hook accepts 2 arguments — a function compute that computes a result, and the depedencies array:

const memoizedResult = useMemo(compute, dependencies);

During initial rendering, useMemo(compute, dependencies) invokes compute, memoizes the calculation result, and returns it to the component.

If the dependencies don’t change during the next renderings, then useMemo hook doesn’t invoke compute, but returns the memoized value.

But if the dependencies change during re-rendering, then useMemo hook invokes compute, memoizes the new value, and returns it.

That’s the essence of useMemo hook.

If your computation callback uses props or state values, then be sure to indicate these values as dependencies:

const memoizedResult = useMemo(() => {
  return expensiveFunction(propA, propB);
}, [propA, propB]);

How to Use the useMemo Hook

To use the useMemo hook, follow these steps:

Step 1: Import the useMemo function from the React library.

import { useMemo } from 'react';

Step 2: In your functional component, declare your memoized value using the useMemo hook.

const memoizedValue = useMemo(() => {
  // Your expensive calculation or function here
  // This function will only run when the dependencies change
  return result;
}, [dependency1, dependency2]);

The first argument to useMemo hook is a function that returns the memoized value. This function will only be executed when the dependencies (specified in the second argument) change. The memoized value is then returned.

Use the memoizedValue in your component as needed:

return (
  <div>
    {/* Use the memoized value here */}
    <p>Memoized Value: {memoizedValue}</p>
  </div>
);

By providing an array of dependencies, you control when the memoized value should be recalculated.

If any dependencies in the array change, the function inside useMemo hook will run again, and the new memoized value will be returned. The previous memoized value will be used if none of the dependencies change.

useMemo(): An Example – 1

Now let’s make a simple application to demonstrate the use of useMemo hook.

This program has the following components:

  • Increment button: starts from 0 and increase the count by 1
  • Even num button: starts from 2 and returns even numbers going forward
  • Also an evenNumDoouble() function which will return the twice value of the even number

WithoutUseMemo.jsx

import { useState } from 'react';

const WithoutUseMemo = () => {
  const [count, setCount] = useState(0);
  const [evenNum, setEvenNum] = useState(2);

  function evenNumDouble() {
    console.log('double');
    return evenNum * 2;
  }

  return (
    <div>
      <h3>Counter: {count}</h3>
      <h3>Even Numbers: {evenNum}</h3>
      <h3>even Number Double Value: {evenNumDouble()}</h3>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setEvenNum(evenNum + 2)}>Even Numbers</button>
    </div>
  );
};

export default WithoutUseMemo;

App.jsx

import WithoutUseMemo from './WithoutUseMemo';

function App() {
  return (
    <div>
      <WithoutUseMemo />
    </div>
  );
}

export default App;

In the above code we will find out the below points:

  • When we click the button Even Numbers then the function evenNumDouble() is called since the state of evenNum is changed
  • But clicking the button Increment also renders the evenNumDouble() function although the count state is not changing
without-usememo-hook

This means that every time the evenNumDouble() function is rendered unnecessarily on the page which reflects a less efficient code, we will fix this through the useMemo hook below:

WithUseMemo.jsx

import React, { useState, useMemo } from 'react';

const WithUseMemo = () => {
  const [count, setCount] = useState(0);
  const [evenNum, setEvenNum] = useState(2);
  const memoHook = useMemo(
    function evenNumDouble() {
      console.log('double');
      return evenNum * 2;
    },
    [evenNum]
  );

  return (
    <div>
      <h3>Counter: {count}</h3>
      <h3>Even Numbers: {evenNum}</h3>
      <h3>even Number Double Value: {memoHook}</h3>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setEvenNum(evenNum + 2)}>Even Numbers</button>
    </div>
  );
};

export default WithUseMemo;

App.jsx

import WithUseMemo from './WithUseMemo';


function App() {
  return (
    <div>
      <WithUseMemo/>
    </div>
  );
}

export default App;

In the above code, we have set the output of evenNumDouble() function into a constant memoHook which will filter the function through the useMemo hook to check only if the specified variable (which is evenNum in this case) has changed then this function will be rendered otherwise not.

Notice that the changing state variable is specified in square brackets at the end of useMemo hook similar to the useEffect hook.

Also Read: The React useEffect Hook for Absolute Beginners

Now, if we run the above code then we will find out that our code runs the evenNumDouble() function only as required and not unnecessarily.

with-usememo-hook

In the same manner, if you have a large code base and your application is running slow then you can check whether there are any unnecessary renders on the page and restrict them using the useMemo hook, this definitely speeds up your app and makes it more efficient.

Other cases that can be used:

  • Filters
  • Math operations
  • Lists
  • Reducers functions

useMemo(): An Example – 2

Let’s take one more example.

Suppose we have a static Welcome Card to be displayed inside an application. The app also contains other states, for example a counter.

Since the Welcome Card is a child of the main parent App, any state changes inside App will cause the static card to be re-rendered every time the counter is increased.

WelcomeCard.jsx

import { useEffect } from 'react';

const WelcomeCard = () => {
  useEffect(() => {
    console.log('Hey I am rendering again 😂');
  });
  return (
    <div className="card">
      <h2>Hi there!</h2>
      <p>My name is Sunil</p>
      <p>Nice to see you here</p>
    </div>
  );
};

export default WelcomeCard;

App.jsx

import { useState } from "react";
import './App.css';
import WelcomeCard from './WelcomeCard';


function App() {
	const [ctr, setCtr] = useState(0);
  return (
    <div>
			<h1>Application</h1>
      <button onClick={() => setCtr(ctr + 1)}>
        You clicked me {ctr} times.
      </button>
      <WelcomeCard/>
    </div>
  );
}

export default App;

App.css

body {
	text-align: center;
}

.card {
	background-color: aliceblue;
	display: block;
	width: 50%;
	margin: 0 auto;
	padding: 10px;
	border: 1px solid gray;
}
button {
	margin-bottom: 20px;
}

Output:

welcome-card-without-usememo-react-hook

As we can see, the WelcomeCard is rendered again every time we click on the counter, in fact it is rendered more times than the counter.

This is happening even though there is nothing that is dynamic inside the card itself, thus the re-rendering is a waste.

Now imagine a website with lots of static data components, which re-render every time states or states of parents change.

To avoid this we can use useMemo as follows:-

App.jsx

import { useState, useMemo } from 'react';
import './App.css';
import WelcomeCard from './WelcomeCard';


function App() {
  const [ctr, setCtr] = useState(0);
  const memoizedWelcomeCard = useMemo(() => {
    return <WelcomeCard />;
  }, []);
  return (
    <div>
      <h1>Application</h1>
      <button onClick={() => setCtr(ctr + 1)}>
        You clicked me {ctr} times.
      </button>
      {memoizedWelcomeCard}
    </div>
  );
}

export default App;

WelcomeCard.jsx

import { useEffect } from 'react';

const WelcomeCard = () => {
  useEffect(() => {
    console.log('Hey I am rendering again 😂');
  });
  return (
    <div className="card">
      <h2>Hi there!</h2>
      <p>My name is Sunil</p>
      <p>Nice to see you here</p>
    </div>
  );
};

export default WelcomeCard;

This ensures that the memoized card is only rendered at the initial page loading time, and doesn’t re-render every time the counter is clicked, no matter how high the value.

welcome-card-with-usememo-react-hook

When to Run the useMemo Hook?

It’s important to note that the useMemo hook should be used when you have expensive calculations or functions that rely on the specified dependencies.

If you have a simple value that doesn’t require expensive computation, you can use the regular state or props variables.

Here are a few scenarios where using useMemo can be beneficial:

Expensive Calculations: Suppose you have a calculation that takes significant time or processing power, such as complex mathematical operations or heavy data manipulation.

In that case, you can use useMemo hook to memoize the result. This ensures that the calculation is only performed when necessary, preventing unnecessary re-computations.

Rendering Optimization: React re-evaluates all expressions and functions within the component’s scope when rendering a component. If you have a function called during rendering and its result doesn’t change frequently, you can use useMemo hook to memoize the result.

This prevents the function from being called unnecessarily on each render, improving performance.

Dependency-based Computations: Sometimes you have a function or computation that depends on certain values or props. If the result of the computation remains the same as long as the dependencies don’t change, you can use useMemo hook to memoize the result.

This ensures the computation is only executed when the dependencies change, avoiding unnecessary recalculations.

Preventing Unnecessary Re-renders: React components re-render when there is a change in their state or props.

However, there might be scenarios where a component receives new props but doesn’t need to re-render because the computation result remains the same.

In such cases, you can use useMemo hook to memoize the computed value and prevent unnecessary re-renders.

Recommendations

  • Any optimization added too early is a risk because the optimized code may change many times during the process, so the recommendation is to apply optimization after the main core of code related to a specific feature or code was done.
  • Is necessary to check the performance render before and after useMemo just to make sure that render speed increases.
  • Be careful with increasing complexity in the components when using useMemo.

Conclusion

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

useMemo can help the performance of an application by “remembering” expensive functions and preventing a re-render every time there is a change in the application.

While performance can be improved by using this hook, it can also slow down your application if you overuse it. The more you use the hook, the more your application has to allocate memory.

Feel free to leave a comment below in case you have any questions or feedback to offer on this article.

See you on the next one. Cheers!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Similar articles you may like

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.

Add comment

Stay Updated

Want to be notified when our article is published? Enter your email address below to be the first to know.

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.