React Tutorials
React ES6
React Hooks
useMemo
HookReact useMemo
Hook returns the memorized value.
Think of memorization as keeping the value so that it does not need to be recalculated.
useMemo
Hook only works when some of its dependencies are updated.
This can improve performance.
useMemo
and useCallback
Hooks are the same. The main difference is that useMemo
returns a memorized value and useCallback
returns a memorized function. You can learn more about useCallback in the useCallback
chapter.
The useMemo
Hook can be used to store expensive, resource-intensive operations.
In this example, we have an expensive function that works in every case.
If you change the number or add function, you will notice a performance delay.
A poor performing function. The expensiveCalculation
function runs on every render:
import { useState } from "react";
import ReactDOM from "react-dom";
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>
<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;
};
ReactDOM.render(<App />, document.getElementById('root'));
useMemo
To fix this performance problem, we can use the useMemo
Hook to memorize an expensiveCalculation
function. This will only allow the function to work if needed.
We can wrap up an expensive work call with a useMemo
.
useMemo
Hook accepts the second parameter to declare dependency. Expensive work will only work when its dependence has changed.
In the following example, an expensive task will only work if the count
is changed and not when the input is added.
Performance example using the useMemo
Hook:
import { useState, useMemo } from "react";
import ReactDOM from "react-dom";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const calculation = useMemo(() => expensiveCalculation(count), [count]);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
<div>
<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;
};
ReactDOM.render(<App />, document.getElementById('root'));