useMemo in React

The useMemo hook in React is a powerful tool for optimizing performance by memoizing expensive computations. By using useMemo, you can avoid unnecessary recalculations, especially in large and complex applications where performance is critical. This chapter explores the useMemo hook in depth, from basic usage to advanced techniques, with practical examples to demonstrate its benefits.

Understanding useMemo

The useMemo hook returns a memoized value, which is recomputed only when one of its dependencies changes. It helps to optimize performance by skipping expensive calculations if the inputs (dependencies) haven’t changed.

Syntax:

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

				
			
  • The first argument is a function that computes the value.
  • The second argument is an array of dependencies. The memoized value is recalculated only when one of these dependencies changes.

Basic Usage

Let’s start with a simple example to understand the basic usage of useMemo.

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

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  const expensiveCalculation = (num) => {
    console.log('Calculating...');
    for (let i = 0; i < 1000000000; i++) {} // Simulate expensive calculation
    return num * 2;
  };

  const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);

  return (
    <div>
      <h1>useMemo Example</h1>
      <p>Count: {count}</p>
      <p>Expensive Calculation Result: {memoizedValue}</p>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Type something"
      />
    </div>
  );
}

export default App;

				
			

Explanation:

  • State Variables: We have two state variables, count and text.
  • Expensive Calculation: The expensiveCalculation function simulates a CPU-intensive task.
  • Memoization: useMemo memoizes the result of expensiveCalculation(count) and recalculates it only when count changes.
  • Rendering: The memoizedValue is displayed alongside the count and a text input.

Output:

When you run this application, you’ll see the count and the result of the expensive calculation. The console will log “Calculating…” only when the count changes, not when the text input is updated.

Practical Examples

Filtering Large Data Sets

In this example, we will use useMemo to efficiently filter a large list of items based on user input.

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

const items = Array.from({ length: 10000 }, (_, i) => `Item ${i + 1}`);

function App() {
  const [search, setSearch] = useState('');

  const filteredItems = useMemo(() => {
    console.log('Filtering items...');
    return items.filter((item) =>
      item.toLowerCase().includes(search.toLowerCase())
    );
  }, [search]);

  return (
    <div>
      <h1>useMemo Filtering Example</h1>
      <input
        type="text"
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        placeholder="Search items"
      />
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

				
			

Explanation:

  • Large Data Set: We have a large array of items (items) with 10,000 elements.
  • Filtering: The filteredItems array is computed using useMemo and recalculated only when search changes.
  • Search Input: The search state is updated via an input field, and the filtered items are displayed in a list.

Output:

When you run this application, you’ll see a search input and a list of items. The console will log “Filtering items…” only when the search input changes, demonstrating efficient filtering of the large data set.

Memoizing Component Render

In this example, we will memoize a component that performs an expensive render operation to optimize performance.

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

function ExpensiveComponent({ count }) {
  console.log('Rendering ExpensiveComponent...');
  for (let i = 0; i < 1000000000; i++) {} // Simulate expensive render
  return <p>Expensive Component Count: {count}</p>;
}

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  const memoizedComponent = useMemo(() => {
    return <ExpensiveComponent count={count} />;
  }, [count]);

  return (
    <div>
      <h1>useMemo Component Example</h1>
      {memoizedComponent}
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Type something"
      />
    </div>
  );
}

export default App;

				
			

Explanation:

  • Expensive Component: ExpensiveComponent simulates an expensive render operation.
  • Memoization: useMemo memoizes the ExpensiveComponent and re-renders it only when count changes.
  • Rendering: The memoized component is displayed alongside the count and a text input.

Output:

When you run this application, you’ll see the count and the expensive component. The console will log “Rendering ExpensiveComponent…” only when the count changes, not when the text input is updated, demonstrating optimized rendering.

Advanced Usage

Memoizing Callbacks with useMemo

useMemo can also be used to memoize callbacks, though useCallback is more commonly used for this purpose. However, let’s see how useMemo can achieve the same.

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

function Child({ onClick }) {
  console.log('Rendering Child...');
  return <button onClick={onClick}>Click Me</button>;
}

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  const memoizedCallback = useMemo(() => {
    return () => {
      setCount((prevCount) => prevCount + 1);
    };
  }, []);

  return (
    <div>
      <h1>useMemo Callback Example</h1>
      <Child onClick={memoizedCallback} />
      <p>Count: {count}</p>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Type something"
      />
    </div>
  );
}

export default App;

				
			

Explanation:

  • Callback Memoization: memoizedCallback is memoized using useMemo and recalculated only once because it has an empty dependency array.
  • Child Component: The Child component uses the memoized callback.
  • Rendering: The Child component is re-rendered only when memoizedCallback changes.

Output:

When you run this application, you’ll see a button and a count. The console will log “Rendering Child…” only once, demonstrating the memoized callback’s effectiveness.

Practical Example 1: Memoizing a Computation-Heavy Function

In this example, we will use useMemo to memoize the result of a computation-heavy function. This will help us avoid re-computation when the input data hasn’t changed.

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

function App() {
  const [count, setCount] = useState(0);
  const [otherCount, setOtherCount] = useState(0);

  const expensiveCalculation = (num) => {
    console.log('Performing expensive calculation...');
    for (let i = 0; i < 1000000000; i++) {} // Simulate expensive calculation
    return num * 2;
  };

  const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);

  return (
    <div style={{ padding: '20px' }}>
      <h1>useMemo Example: Expensive Calculation</h1>
      <p>Count: {count}</p>
      <p>Other Count: {otherCount}</p>
      <p>Expensive Calculation Result: {memoizedValue}</p>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <button onClick={() => setOtherCount(otherCount + 1)}>Increment Other Count</button>
    </div>
  );
}

export default App;

				
			

Explanation:

  • State Variables: We have two state variables, count and otherCount.
  • Expensive Calculation: The expensiveCalculation function simulates a CPU-intensive task.
  • Memoization: useMemo memoizes the result of expensiveCalculation(count) and recalculates it only when count changes.
  • Rendering: The memoizedValue is displayed alongside the count and other count values.

Output:

When you run this application, you’ll see the counts and the result of the expensive calculation. The console will log “Performing expensive calculation…” only when the count changes, not when the other count is updated.

Practical Example 2: Filtering a Large List

In this example, we will use useMemo to efficiently filter a large list of items based on user input. This can help to optimize performance when working with large data sets.

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

const items = Array.from({ length: 10000 }, (_, i) => `Item ${i + 1}`);

function App() {
  const [search, setSearch] = useState('');

  const filteredItems = useMemo(() => {
    console.log('Filtering items...');
    return items.filter((item) =>
      item.toLowerCase().includes(search.toLowerCase())
    );
  }, [search]);

  return (
    <div style={{ padding: '20px' }}>
      <h1>useMemo Example: Filtering Large List</h1>
      <input
        type="text"
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        placeholder="Search items"
      />
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

				
			

Explanation:

  • Large Data Set: We have a large array of items (items) with 10,000 elements.
  • Filtering: The filteredItems array is computed using useMemo and recalculated only when search changes.
  • Search Input: The search state is updated via an input field, and the filtered items are displayed in a list.

Output:

When you run this application, you’ll see a search input and a list of items. The console will log “Filtering items…” only when the search input changes, demonstrating efficient filtering of the large data set.

The useMemo hook in React is essential for optimizing performance by memoizing expensive computations and preventing unnecessary recalculations. By understanding and effectively using useMemo, you can enhance the efficiency of your React applications, especially in scenarios involving large data sets, complex calculations, and expensive renders. Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India