React useMemo Hook

React useMemo Hook

The useMemo Hook is a performance optimization tool very similar to useCallback. However, while useCallback caches a function definition, useMemo caches the result of a calculation (a returned value).

The word "memo" comes from memoization, a computer science term for caching the result of an expensive function call so you don't have to compute it again if the inputs haven't changed.


The Problem: Expensive Calculations on Re-render

React components re-render when state or props change. If you have a computationally heavy operation (like filtering a massive list, complex math, or sorting 10,000 items) inside your component, it will re-calculate every single time the component renders, even if the render was triggered by an unrelated state change (like typing in an unrelated input field).

This can severely degrade the performance of your application.


The Solution: useMemo

useMemo takes two arguments:

  1. A "create" function that performs the heavy calculation and returns a value.
  2. A dependency array.

React will only execute the "create" function when one of the dependencies has changed. Otherwise, it skips the calculation and simply returns the cached value from the previous render.

Syntax

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Example Scenario

In this example, we have an expensive calculation that finds prime numbers. Without useMemo, clicking the "Toggle Theme" button would force the prime numbers to recalculate, causing the app to freeze momentarily.

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

// A fake expensive math function function calculatePrimes(iterations) { console.log("Calculating heavy math..."); let primes = []; // ... imagine heavy loop here ... return primes; }

function App() { const [count, setCount] = useState(100); const [isDarkMode, setIsDarkMode] = useState(false);

// Wrap the heavy operation in useMemo const primesList = useMemo(() => { return calculatePrimes(count); }, [count]); // Only recalculate if 'count' changes!

return ( <div style={{ background: isDarkMode ? '#333' : '#FFF' }}> <button onClick={() => setIsDarkMode(!isDarkMode)}> Toggle Theme (Fast!) </button> <button onClick={() => setCount(count + 10)}> Calculate More Primes (Slow) </button> <p>Primes calculated.</p> </div> ); }

Because we wrapped calculatePrimes in useMemo, clicking "Toggle Theme" does not recalculate the primes. React sees that count hasn't changed, skips the function, and uses the cached primesList.


useMemo vs useCallback

It is very common to confuse these two hooks. Just remember:

Actually, useCallback(fn, deps) is mathematically equivalent to useMemo(() => fn, deps).


When Not to Use useMemo

Do not use useMemo prematurely. Caching values costs memory. If the calculation is very fast (e.g., mapping over an array of 50 items), wrapping it in useMemo will actually make your app slower because the overhead of running the useMemo checks takes longer than the calculation itself.

Write your code normally first. Only introduce useMemo when you notice a specific performance bottleneck.


Warning: The function passed to useMemo runs during rendering. Do not do anything there that you wouldn’t normally do while rendering. Side effects (like fetching data or modifying the DOM) belong in useEffect, not useMemo.


Exercise

?

Which scenario is the most appropriate use case for useMemo?