React useMemo Hook


React 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.



Performance

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.


Example

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'));
            


use 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.


Example

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'));