ReactJS useMemo Hook

Before diving into useMemo, it’s important to understand what a calculation means in this context. A calculation refers to any JavaScript logic that generates a value. This can include operations such as loops, filter, map, reduce, or even complex mathematical computations. By default, every time a React component re-renders, all of this logic executes again—even when the underlying input data remains unchanged.

This can include:
  • looping through large arrays
  • filtering lists/sorting data
  • performing mathematical operations
  • deriving values from props or state

The useMemo Hook exists to avoid repeating unnecessary work.


What Is useMemo?

useMemo is a React Hook that stores (caches) the result of a calculation and returns the same stored value on future renders as long as the inputs remain unchanged.

As React applications grow, components often perform calculations based on props or state. While React efficiently updates the UI, some calculations can be expensive and unnecessary to repeat on every render. This is where the useMemo Hook becomes useful.
In simpler words:

useMemo prevents React from recalculating the same derived value again and again when the inputs are the same.


Importing useMemo


import { useMemo } from "react";


Basic Syntax of useMemo


const memoizedValue = useMemo(() => {
  return computeValue();
}, [dependencies]);

What This Means:
  • The function runs once initially
  • React stores the returned value
  • The function runs again only when dependencies change

Why Do We Need useMemo?

React re-renders components whenever:
  • state changes
  • props change
  • parent re-renders

Without useMemo, calculations inside components run again on every render, even when inputs haven’t changed

This can cause:
  • performance issues
  • slow UI updates
  • unnecessary CPU usage

Expensive Calculation With And Without useMemo

Example 1 : Calculation without useMemo


import { useState } from "react";

function WithoutMemo() {
  const [count, setCount] = useState(0);

  function heavyCalculation(num) {
    console.log("Calculating...");
    let total = 0;
    for (let i = 0; i < 100000; i++) {
      total += num;
    }
    return total;
  }

  const result = heavyCalculation(count);

  return (
    <>
      <p>Result: {result}</p>
      <button onClick={() => setCount(count + 1)}>
        Increase
      </button>
    </>
  );
}

export default WithoutMemo;

Problem Here:
  • heavyCalculation() runs on every render
  • Even unrelated re-renders trigger it
  • App feels slow

Example 2: Same Calculation with useMemo


import { useState, useMemo } from "react";

function WithMemo() {
  const [count, setCount] = useState(0);

  const result = useMemo(() => {
    console.log("Calculating...");
    let total = 0;
    for (let i = 0; i < 100000000; i++) {
      total += count;
    }
    return total;
  }, [count]);

  return (
    <>
      <p>Result: {result}</p>
      <button onClick={() => setCount(count + 1)}>
        Increase
      </button>
    </>
  );
}

export default WithMemo;

Step-by-Step Explanation:
  1. Component renders
  2. useMemo runs calculation
  3. Result is stored
  4. Component re-renders
  5. If count is unchanged → cached value is reused
  6. If count changes → calculation runs again

What useMemo Actually Stores

useMemo stores:
  • the returned value, not the function
  • based on dependency comparison
  • using shallow comparison

Filtering a List (Very Common Case)


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

function App() {
  const [users, setUsers] = useState([]);
  const [search, setSearch] = useState("");

  // Fetch users using useEffect
  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(res => res.json())
      .then(data => setUsers(data));
  }, []);

  // Memoize filtered users
  const filteredUsers = useMemo(() => {
    return users.filter(user =>
      user.username.toLowerCase().includes(search.toLowerCase())
    );
  }, [users, search]);

  return (
    <>
      <input
        placeholder="Search user"
        value={search}
        onChange={(e) => setSearch(e.target.value)}
      />

      <ul>
        {filteredUsers.map(user => (
          <li key={user.id}>
            {user.username}
          </li>
        ))}
      </ul>
    </>
  );
}

export default App;

Why useMemo Helps Here
  • Filtering is expensive
  • Runs only when users or search changes
  • Improves responsiveness

Final Summary

The useMemo Hook allows React to reuse previously calculated values, improving performance by avoiding unnecessary recalculations during re-renders. It is best used for expensive computations or derived data that depends on specific values. When applied correctly, useMemo makes React applications faster and more efficient without changing their behavior.

Simple Rule to Remember: useMemo is about performance, not logic.