React useMemo Hook

In website design, sometimes heavy calculations and processes need to be done. To prevent recalculation of these types of calculations and operations in every rendering, we use the useMemo hook in React. This hook memorizes the previous value of the function so that we can use it if needed.

The React useMemo hook will rerun the operation when its dependencies change. As mentioned, a heavy operation or calculation is done once. Using this hook it is stored in the memory and we use it when needed and there is no need to do the same operation and calculations again.

What is the useMemo hook in React?

By default, React will re-run the entire body of your component every time that it re-renders. React has a built-in hook called useMemo that allows you to memoize expensive functions and heavy calculations so this hook lets you cache the result of the calculation between re-renders.

Think of memoization as caching a value so that it does not need to be recalculated. This can improve your website performance.

How to use useMemo?

The useMemo hook can be used to keep expensive, resource-intensive functions from needlessly running in every rendering.

useMemo is a Hook, so you can only call it at the top level of your component or your own Hooks. You can’t call it inside loops or conditions.

You simply pass in A calculation function that takes no arguments, like () =>, and returns what you wanted to calculate and an array of dependencies. The useMemoHook accepts a second parameter to declare dependencies and will only recompute the memoized value when one of the dependencies has changed. The useMemo Hook only runs when one of its dependencies updates. This will cause the function to only run when needed.

On every subsequent render, React will compare the dependencies with the dependencies you passed during the last render. If none of the dependencies have changed (compared with Object.is), useMemo will return the value you already calculated before. Otherwise, React will re-run your calculation and return the new value.

const cachedValue = useMemo(calculateValue, dependencies)
  • calculateValue: The function calculates the value that you want to cache. React will call your function during the initial render. On the next renders, React will return the same value again if they dependencies have not changed since the last render.
  • dependencies: The list of all reactive values referenced inside of the calculateValue code. Reactive values include props, state, and all the variables and functions declared directly inside your component body.

In this example, we have an expensive function that runs on every render.

import { useState } from "react";
import ReactDOM from "react-dom/client";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const cachedValue = 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;
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

But in this example, we have used the useMemo hook, which saves the return value and prevents the function from running again for heavy calculations until the value of one of the dependencies changes.

import { useState, useMemo } from "react";
import ReactDOM from "react-dom/client";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const cachedValue = 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>
        {cachedValue}
      </div>
    </div>
  );
};

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

In this example, we have an expensive function called expensiveCalculation. In the first example, this function was executed every time it was rendered, but in this example, the useMemo hook prevents it from being executed again. The dependency of this function is the “count” variable, if its value changes, the expensiveCalculation function will be executed again.

Usually, this isn’t a problem because most calculations are very fast. However, if you’re filtering or transforming a large array, or doing some expensive computation, you might want to skip doing it again if data hasn’t changed.

Shopping Cart