If you are not already familiar with the concept of hooks, be sure to check this article, as it provides a very good, in-depth overview of the concept of hooks, as well as some examples of them.
Introduction
The useMemo
hook is used to return a cached value in order to save any re-computation overhead. It works similarly to the useCallback
hook; you can read more about it here.
The useMemo
hook is used to prevent a component from re-rendering unless its props have changed, meaning that we are now allowed to isolate resource-intensive computed values so that they won’t automatically run on every component render.
It would be better to showcase a scenario where it would be beneficial to use the hook so we can get a better understanding of the steps we’ve taken to reach an issue, and then explain the thought process behind using the useMemo
hook.
Project Overview
We’ll start by scaffolding a brand-new React project. First, we’ll create a new project directory, after which we’ll initialize a new project using the terminal.
You can use either npm, npx, or yarn for this process. The command you would be running is:
- npm:
npm init react-app app-name
- npx
: npx create-react-app app-name
- yarn:
yarn create react-app app-name
Now that we’ve got everything set up, let’s get right to the fun part.
Project Progression
Since this is a small project we’ll put all of the code inside the App.js
file under the root src
directory, which will look something like this:
import { useState } from "react";
import "./App.css";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const calculation = expensiveCalculation(count);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
<div className="App">
<div>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
<button onClick={addTodo}>Add Todo</button>
</div>
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
<h2>Expensive Calculation</h2>
{calculation}
</div>
</div>
);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000000; i++) {
num += 1;
}
return num;
};
export default App;
The application from above is rather straightforward; we have a list of todos, a counter element, and finally, a function that once called, triggers some expensive calculations.
You can notice that the function is called each time the component re-renders.
So, what’s the issue?
When adding a new todo you will notice that there is a slight delay before anything happens. That is not expected, as both visually and functionality-wise they are unrelated.
The root cause of the issue
The delay is caused by the expensive computation that is being triggered by each re-render of the App
component. The re-renders of the App
component are caused by its changes in state.
Solution
This is a perfect scenario for the usage of the useMemo
hook, as it has been conceived to help us improve performance when dealing with expensive computations such as function calls.
By wrapping our expensiveCalculation
function call within the useMemo
hook, we will ensure that the result of this function call will only be recomputed when the values from the dependency array that the hook takes as a secondary argument change, otherwise it will be cached and not be influenced by external state changes or component re-renders.
With useMemo
, our expensiveCalculation
function will rather be used like this:
const calculation = useMemo(() => expensiveCalculation(count), [count]);
By passing the count
variable to the useMemo
‘s hook dependency array we let React know that unless the value of count
variable changes, we’ll want to change the result of the expensiveCalculation
function call.
If you were to now try reloading your browser tab and tried adding a new todo, you would be able to notice that it no longer lags behind:
That’ll only happen when updating the value of the count
state variable, which is expected.
You can learn more about the
memo
HoC here. The functionality is similar to theuseMemo
hook, the difference being the syntax. You can check a realistic use-case in this article.
Summary
I hope you have enjoyed reading this article and that you’ve got a better understanding of what the useMemo
hook is, what it does, and also when you should be using it.
Feel free to leave a comment below in case you have any questions, inquiries, or feedback to offer on this article.
See you on the next one. Cheers!
💬 Leave a comment