Tell us about the useMemo hook, how it works, where it's applied and for what purpose?

👨‍💻 Frontend Developer 🟡 Often Asked 🎚️ Medium
#React #Hooks

Brief Answer

useMemo is a React hook that allows you to memoize (cache) computation results between renders. It prevents repeated calculations on every render if dependencies haven’t changed.

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

Key features:

  • Optimizes performance by caching results of expensive computations
  • Recalculates value only when dependencies change
  • Doesn’t replace useState or useEffect, but complements them
  • Can be used to stabilize objects and functions between renders

Usage example:

function ExpensiveCalculation({ number }) {
  const expensiveValue = useMemo(() => {
    console.log('Calculating...');
    return number * 2;
  }, [number]);
  
  return <div>Result: {expensiveValue}</div>;
}

Full Answer

The useMemo hook is one of React’s built-in hooks designed to optimize performance by memoizing computation results. It helps avoid repeated expensive calculations on every component render. 🚀

How useMemo works?

useMemo takes two parameters:

  1. Compute function — which returns the result
  2. Dependencies array — when these change, recalculation occurs
import React, { useMemo } from 'react';
 
function Component({ a, b }) {
  const memoizedValue = useMemo(() => {
    // Expensive calculations
    return a * b;
  }, [a, b]); // Recalculates only if a or b changed
  
  return <div>Result: {memoizedValue}</div>;
}

When component renders:

  1. React checks dependencies array
  2. If dependencies haven’t changed, returns cached value
  3. If dependencies changed, executes function and caches new result

Main useMemo applications

1. Optimizing expensive calculations

function FibonacciCalculator({ number }) {
  const fibonacci = useMemo(() => {
    console.log('Calculating Fibonacci number...');
    if (number <= 1) return number;
    
    let a = 0, b = 1;
    for (let i = 2; i <= number; i++) {
      [a, b] = [b, a + b];
    }
    return b;
  }, [number]);
  
  return <div>Fibonacci number: {fibonacci}</div>;
}

2. Stabilizing objects

function UserProfile({ user }) {
  const userInfo = useMemo(() => ({
    name: user.firstName + ' ' + user.lastName,
    avatar: user.photoUrl,
    isAdmin: user.role === 'admin'
  }), [user]);
  
  // userInfo will be stable between renders
  return <UserCard user={userInfo} />;
}

3. Preventing unnecessary child component re-renders

function Parent({ items }) {
  // Without useMemo object is created anew on every render
  // const processedItems = items.map(item => ({ ...item, processed: true }));
  
  // With useMemo object is stable between renders
  const processedItems = useMemo(() => 
    items.map(item => ({ ...item, processed: true })),
    [items]
  );
  
  return <Child items={processedItems} />;
}
 
// In child component you can use React.memo
const Child = React.memo(function Child({ items }) {
  return (
    <ul>
      {items.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
});

When to use useMemo

Use useMemo when:

  1. Expensive calculations — processing large arrays, complex mathematical calculations
  2. Object creation — to avoid creating new objects on every render
  3. Passing to child components — to optimize with React.memo
  4. Working with large lists — filtering, sorting, transforming data
function ProductList({ products, searchTerm, category }) {
  // Filtering and sorting - expensive operations
  const filteredProducts = useMemo(() => {
    return products
      .filter(product => 
        product.name.toLowerCase().includes(searchTerm.toLowerCase()) &&
        product.category === category
      )
      .sort((a, b) => a.price - b.price);
  }, [products, searchTerm, category]);
  
  return (
    <ul>
      {filteredProducts.map(product => 
        <ProductItem key={product.id} product={product} />
      )}
    </ul>
  );
}

When to avoid useMemo

Avoid useMemo when:

  1. Simple calculations — basic arithmetic, simple operations
  2. Frequently changing dependencies — if dependencies change often, cache will constantly reset
  3. Small data arrays — optimization not needed for small datasets
  4. Simple objects — if objects are created quickly and don’t affect performance
// ❌ Don't use useMemo for simple operations
function BadExample({ a, b }) {
  const sum = useMemo(() => a + b, [a, b]); // Overkill!
  return <div>{sum}</div>;
}
 
// ✅ Just use a variable
function GoodExample({ a, b }) {
  const sum = a + b; // Simple and efficient
  return <div>{sum}</div>;
}

Common mistakes

1. Using useMemo unnecessarily

// ❌ Overuse
function Component({ name }) {
  const greeting = useMemo(() => `Hello, ${name}!`, [name]);
  return <h1>{greeting}</h1>;
}
 
// ✅ Just use a variable
function Component({ name }) {
  const greeting = `Hello, ${name}!`;
  return <h1>{greeting}</h1>;
}

2. Incorrect dependencies array

// ❌ Error: missing dependency
function Component({ user }) {
  const fullName = useMemo(() => {
    return user.firstName + ' ' + user.lastName;
  }, []); // user not in dependencies list!
  return <div>{fullName}</div>;
}
 
// ✅ Correctly: all dependencies specified
function Component({ user }) {
  const fullName = useMemo(() => {
    return user.firstName + ' ' + user.lastName;
  }, [user]);
  return <div>{fullName}</div>;
}

3. Mutating objects inside useMemo

// ❌ Error: mutating object
function Component({ items }) {
  const processedItems = useMemo(() => {
    items.forEach(item => item.processed = true); // Mutating!
    return items;
  }, [items]);
  return <List items={processedItems} />;
}
 
// ✅ Correctly: creating new object
function Component({ items }) {
  const processedItems = useMemo(() => {
    return items.map(item => ({ ...item, processed: true })); // Creating new
  }, [items]);
  return <List items={processedItems} />;
}

Summary

useMemo is a React hook for:

  • Memoizing results of expensive computations
  • Optimizing component performance
  • Stabilizing objects and functions between renders
  • Preventing unnecessary re-renders of child components

When to use:

  • Expensive calculations (filtering, sorting large arrays)
  • Creating complex objects
  • Passing stable values to child components
  • Working with large datasets

When to avoid:

  • Simple calculations (addition, string concatenation)
  • Frequently changing dependencies
  • Small datasets
  • When performance is not critical

Best practices:

  • Use only when really needed
  • Always specify correct dependencies array
  • Don’t mutate objects inside useMemo
  • Don’t use for side effects (use useEffect for that)

useMemo is a powerful optimization tool, but it shouldn’t be used mindlessly. First identify real performance issues, then apply useMemo to solve them. 🚀


Want more articles to prepare for interviews? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪