🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
REFERENCEreact

react Documentation

LOADING ENGINE...

useMemo

AI & DATA SCIENCE // usememo

useMemo caches (memoizes) the result of an expensive computation between renders, only recomputing it when one of its listed dependencies actually changes.

Syntax

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

Deep Dive Course

Without memoization, a value computed directly in a component's function body gets recalculated from scratch on every single render, even if the inputs it depends on haven't changed at all — useMemo wraps that computation in a function, and only re-runs it when one of the values in the dependency array has actually changed since the last render, returning the previously cached result otherwise. This is specifically useful for computations that are genuinely expensive, like processing a large array, or for producing a stable object/array reference that needs to avoid changing identity on every render, such as when it's passed as a prop to a child wrapped in React.memo().

1Understanding useMemo

Without memoization, a value computed directly in a component's function body gets recalculated from scratch on every single render, even if the inputs it depends on haven't changed at all — useMemo wraps that computation in a function, and only re-runs it when one of the values in the dependency array has actually changed since the last render, returning the previously cached result otherwise. This is specifically useful for computations that are genuinely expensive, like processing a large array, or for producing a stable object/array reference that needs to avoid changing identity on every render, such as when it's passed as a prop to a child wrapped in React.memo().

💡

Don't reach for useMemo by default on every computed value — it adds its own small overhead and complexity, and is only actually worth it for computations that are either genuinely expensive or need a stable reference for something like a memoized child component's props.

editor.html
import { useMemo } from 'react';

function ProductList({ products, filter }) {
  const filtered = useMemo(() => {
    console.log('Filtering products...');
    return products.filter(p => p.category === filter);
  }, [products, filter]);
  return <ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
localhost:3000

2Practical Example

Here is a real-world application of useMemo showing how it is used in production React code.

editor.html
import { useMemo } from 'react';

function Cart({ items }) {
  const total = useMemo(() => {
    return items.reduce((sum, item) => sum + item.price, 0);
  }, [items]);
  return <p>Total: ${total}</p>;
}

// items = [{ price: 10 }, { price: 25 }, { price: 5 }]
localhost:3000

3Best Practices

Follow these guidelines when working with useMemo:

1. Reserve useMemo for computations that are either measurably expensive or need to maintain a stable object/array reference between renders, not for cheap calculations

2. Include every value the memoized computation actually depends on in the dependency array, exactly like useEffect's dependency array rules

3. Pair useMemo-produced stable references with a React.memo()-wrapped child component when the goal is specifically avoiding that child's unnecessary re-renders

⚠️

Tip: Don't reach for useMemo by default on every computed value — it adds its own small overhead and complexity, and is only actually worth it for computations that are either genuinely expensive or need a stable reference for something like a memoized child component's props.

editor.html
import { useMemo } from 'react';

function ProductList({ products, filter }) {
  const filtered = useMemo(() => {
    console.log('Filtering products...');
    return products.filter(p => p.category === filter);
  }, [products, filter]);
  return <ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
localhost:3000

4Stabilizing Props for React.memo Children

React.memo skips re-rendering a child when its props are shallowly equal to last time. But an object or array literal built inline as a prop is a new reference every render, which silently defeats React.memo. Wrapping that value in useMemo gives the memoized child a stable reference, so it actually skips re-rendering when the underlying data hasn't changed.

editor.html
// Defeats React.memo: new array reference every render
<List items={data.filter(d => d.active)} />

// Stable reference: React.memo can actually skip re-rendering
const active = useMemo(() => data.filter(d => d.active), [data]);
<List items={active} />
localhost:3000

5useMemo Is Not a Guarantee

useMemo is a performance hint, not a correctness contract — React is allowed to discard a cached value and recompute it in certain situations (memory pressure, components kept offscreen). Code should stay correct even on a render where the memoization didn't actually apply; never rely on useMemo purely to skip running a computation for correctness reasons.

editor.html
// Wrong mental model: 'this only ever runs once'
// Correct mental model: 'this is cached AS AN OPTIMIZATION'
const value = useMemo(() => compute(a, b), [a, b]);
localhost:3000

Examples

Example 01Basic Usage
import { useMemo } from 'react';

function ProductList({ products, filter }) {
  const filtered = useMemo(() => {
    console.log('Filtering products...');
    return products.filter(p => p.category === filter);
  }, [products, filter]);
  return <ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
Example 02Advanced Example
import { useMemo } from 'react';

function Cart({ items }) {
  const total = useMemo(() => {
    return items.reduce((sum, item) => sum + item.price, 0);
  }, [items]);
  return <p>Total: ${total}</p>;
}

// items = [{ price: 10 }, { price: 25 }, { price: 5 }]
Example 03Preserving a Memoized Child's Optimization
import { useMemo, memo } from 'react';

const List = memo(function List({ items }) {
  return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
});

function ProductPage({ data }) {
  const active = useMemo(() => data.filter(d => d.active), [data]);
  return <List items={active} />;
}

Best Practices

  • Reserve useMemo for computations that are either measurably expensive or need to maintain a stable object/array reference between renders, not for cheap calculations
  • Include every value the memoized computation actually depends on in the dependency array, exactly like useEffect's dependency array rules
  • Pair useMemo-produced stable references with a React.memo()-wrapped child component when the goal is specifically avoiding that child's unnecessary re-renders
  • Treat useMemo as a performance optimization only — write code that stays correct even on a render where React decides to discard the cached value
  • Remember useCallback(fn, deps) is equivalent to useMemo(() => fn, deps) — reach for useCallback when memoizing a function itself

Interview Question

Why doesn't wrapping every single computed value in a component with useMemo automatically make the component faster?

Hint: Think about whether useMemo itself is entirely free to use, or whether it has its own small cost.

useMemo itself isn't free: on every render, React still has to check whether the dependency array's values have changed compared to the previous render, which requires storing the previous dependencies and values and doing a comparison, work that has its own small but real cost. For a computation that's already cheap, like adding two numbers or checking a simple condition, that memoization bookkeeping overhead can actually exceed the cost of simply recomputing the value directly every time, making useMemo a net loss rather than a genuine optimization in that case. useMemo is worth its overhead specifically when the wrapped computation is meaningfully more expensive than the memoization bookkeeping itself, like processing or transforming a large array, or when a stable reference, rather than raw computation speed, is the actual goal, such as avoiding breaking a child component's React.memo() optimization.

Exercises

MediumPractice using useMemo in a real scenario.
View Solution
import { useMemo } from 'react';

function ProductList({ products, filter }) {
  const filtered = useMemo(() => {
    console.log('Filtering products...');
    return products.filter(p => p.category === filter);
  }, [products, filter]);
  return <ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
HardA React.memo-wrapped <List items={...} /> re-renders on every parent render because 'items' is built inline. Fix it with useMemo so List only re-renders when the underlying data changes.
View Solution
import { useMemo, memo } from 'react';

const List = memo(function List({ items }) {
  return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
});

function Page({ data }) {
  const sorted = useMemo(() => [...data].sort((a, b) => a.name.localeCompare(b.name)), [data]);
  return <List items={sorted} />;
}

Frequently Asked Questions

Why doesn't wrapping every single computed value in a component with useMemo automatically make the component faster?

useMemo itself isn't free: on every render, React still has to check whether the dependency array's values have changed compared to the previous render, which requires storing the previous dependencies and values and doing a comparison, work that has its own small but real cost. For a computation that's already cheap, like adding two numbers or checking a simple condition, that memoization bookkeeping overhead can actually exceed the cost of simply recomputing the value directly every time, making useMemo a net loss rather than a genuine optimization in that case. useMemo is worth its overhead specifically when the wrapped computation is meaningfully more expensive than the memoization bookkeeping itself, like processing or transforming a large array, or when a stable reference, rather than raw computation speed, is the actual goal, such as avoiding breaking a child component's React.memo() optimization.

Why shouldn't code rely on useMemo to guarantee a computation only runs once?

The React documentation is explicit that useMemo is a performance optimization the runtime is free to discard — in certain situations, like a component kept offscreen or under memory pressure, React may drop a memoized value and recompute it the next time it's needed, even if its dependencies never changed. Code that only works correctly because it assumes a memoized computation runs exactly once — for example, a computation with side effects, or one that mutates shared state — will silently break the moment React exercises that freedom. useMemo should only ever wrap a pure, side-effect-free computation whose result would be identical whether it ran once or many times; that way, whether or not React's cache actually kicks in on a given render has no effect on correctness, only on speed.

Related Functions

usecallbackusestatecomponent-rendering