Skip to content
intermediatePhase 36 · React

useMemo

Optimize expensive computations with useMemo for performance.

30m
0 problems
Topic Progress0%

Memoizing Values

Memoizing Values

useMemo returns a memoized value that only changes when dependencies change.

Basic Usage

import { useMemo } from "react";

function ExpensiveComponent({ data }) {
  const processedData = useMemo(() => {
    // Expensive computation
    return data.map((item) => ({
      ...item,
      computed: heavyCalculation(item)
    }));
  }, [data]); // Only re-computes when data changes

  return (
    <ul>
      {processedData.map((item) => (
        <li key={item.id}>{item.computed}</li>
      ))}
    </ul>
  );
}

Without useMemo

// Bad: Re-computes on every render
function Component({ items, filter }) {
  const filteredItems = items.filter((item) => item.category === filter);
  // filteredItems is a new array every render
}

With useMemo

// Good: Only re-computes when items or filter change
function Component({ items, filter }) {
  const filteredItems = useMemo(
    () => items.filter((item) => item.category === filter),
    [items, filter]
  );
}

Comparing Results

function SortedList({ items, sortKey }) {
  const sortedItems = useMemo(() => {
    return [...items].sort((a, b) => {
      if (a[sortKey] < b[sortKey]) return -1;
      if (a[sortKey] > b[sortKey]) return 1;
      return 0;
    });
  }, [items, sortKey]);

  return (
    <ul>
      {sortedItems.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

When to Use

When to Use

Good Use Cases

  1. Expensive computations
const result = useMemo(() => {
  return performComplexCalculation(data);
}, [data]);
  1. Filtering/sorting large lists
const filteredItems = useMemo(
  () => items.filter((item) => item.active),
  [items]
);
  1. Referential equality for props
const options = useMemo(() => ({
  sort: sortBy,
  filter: filterBy
}), [sortBy, filterBy]);

// Pass to child that checks object equality
<ChildComponent options={options} />

When NOT to Use

  • Simple computations (overhead > benefit)
  • When dependencies change frequently
  • For primitive values (already memoized)

Cost vs Benefit

// Don't useMemo for this
const doubled = useMemo(() => count * 2, [count]);
// Just use: const doubled = count * 2;

// Do useMemo for this
const expensiveResult = useMemo(() => {
  return data.reduce((acc, item) => {
    return acc + complexCalculation(item);
  }, 0);
}, [data]);

Measuring Performance

function Component({ items }) {
  const start = performance.now();
  const result = useMemo(() => {
    return items.map(complexTransform);
  }, [items]);
  const end = performance.now();
  console.log(`Computed in ${end - start}ms`);
}

Performance Impact

Performance Impact

How useMemo Helps

  • Avoids re-computing expensive operations
  • Maintains referential equality for objects/arrays
  • Prevents unnecessary child re-renders

With React.memo

const ChildComponent = React.memo(({ items }) => {
  // Only re-renders if items prop changes (reference equality)
  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
});

function Parent({ filter }) {
  const items = getItems();

  // Without useMemo: new array every render = Child always re-renders
  const filteredItems = items.filter((i) => i.category === filter);

  // With useMemo: same array reference = Child doesn't re-render
  const filteredItems = useMemo(
    () => items.filter((i) => i.category === filter),
    [items, filter]
  );

  return <ChildComponent items={filteredItems} />;
}

Common Pitfalls

// Bad: Empty deps but uses external variable
const result = useMemo(() => compute(value), []); // Missing value!

// Bad: Creating new object in deps
const options = useMemo(() => ({ sort }), [sort]); // OK
// But: <Child options={options} /> // options is new reference each time
// Fix: ensure Child uses memo or callbacks

// Good: Include all dependencies
const result = useMemo(() => compute(a, b), [a, b]);

Performance Checklist

  • Expensive computation (>10ms)
  • Large data transformations
  • Need referential equality
  • Passing to memoized children
  • Dependencies don't change often

Practice Problems

0/3solved
Build useMemo Component

Create a reusable React component implementing useMemo. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
useMemo Testing

Write unit and integration tests for useMemo using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
useMemo Performance

Optimize useMemo for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What does useMemo return?

Question 1 options

2. When should you use useMemo?

Question 2 options

3. What is the benefit of useMemo?

Question 3 options

4. When should you NOT use useMemo?

Question 4 options

Flashcards

Question

What does useMemo do?

Answer

Memoizes a value so it only recalculates when dependencies change

Question

When should you use useMemo?

Answer

For expensive computations with stable dependencies

Question

What is referential equality?

Answer

Two variables pointing to the same object in memory

Question

When should you NOT use useMemo?

Answer

For simple computations where the overhead exceeds the benefit

Question

What is useMemo?

Answer

useMemo is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.useMemo memoizes expensive computations
  • 2.Only re-computes when dependencies change
  • 3.Useful for referential equality
  • 4.Don't use for simple computations
  • 5.Helps prevent unnecessary child re-renders

Interview Tips

  • Explain when useMemo is beneficial
  • Show how it works with React.memo
  • Discuss the cost vs benefit tradeoff

Cheat Sheet

Cheat Sheet

Basic Usage

const result = useMemo(() => {
  return expensiveCalc(data);
}, [data]);

When to Use

  • Expensive computations
  • Filtering/sorting large lists
  • Need referential equality
  • Passing to memoized children

Don't Use For

  • Simple computations
  • Primitive values
  • Dependencies that change often

With React.memo

const Child = React.memo(({ items }) => ...);
const items = useMemo(() => filter(data), [data]);
<Child items={items} /> // Won't re-render if items unchanged