React useMemo Hook

The useMemo hook is used in React to optimize performance by memoizing expensive calculations. It ensures that a computed value is only recalculated when its dependencies change, rather than on every render. This can significantly improve performance in components with heavy computations or frequent re-renders.

1. Example: Expensive Calculation using useMemo Hook

In this example, we use useMemo to memoize the result of an expensive calculation. Without useMemo, the calculation would run on every render, even if the inputs remain unchanged.

Consider the following example, where the rendering can be triggered by the change in input for factorial calculation or, Toggle Other Value button. useMemo helps to remember the value of factorial, even when the re-render is triggered by Toggle Other Value button.

App.js

</>
Copy
import React, { useState, useMemo } from 'react';

function ExpensiveCalculation() {
  const [number, setNumber] = useState(0);
  const [otherValue, setOtherValue] = useState(false);

  const factorial = useMemo(() => {
    console.log('Calculating factorial...');
    const calculateFactorial = (n) => {
      if (n <= 1) return 1;
      return n * calculateFactorial(n - 1);
    };
    return calculateFactorial(number);
  }, [number]); // Recomputes only when 'number' changes

  return (
    <div>
      <h2>Factorial of {number}: {factorial}</h2>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(Number(e.target.value))}
      />
      <br />
      <br />
      <button onClick={() => setOtherValue(!otherValue)}>Toggle Other Value</button>
      <p>Other Value: {otherValue ? 'True' : 'False'}</p>
    </div>
  );
}

export default ExpensiveCalculation;

Explanation:

  • useMemo: Memoizes the result of the factorial calculation and re-computes only when number changes.
  • The factorial function is expensive, but with useMemo, it avoids unnecessary recalculations during renders triggered by other state changes (like otherValue).

Output:


2. Example: Filtering a Large List using useMemo Hook

Here, we use useMemo to optimise the filtering of a large list of items. The filtering logic is only executed when the search query changes, reducing unnecessary computations on each render.

App.js

</>
Copy
import React, { useState, useMemo } from 'react';

function FilteredList() {
  const [search, setSearch] = useState('');
  const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'];

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

  return (
    <div>
      <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 FilteredList;

Explanation:

  • useMemo: Ensures the filtering logic is executed only when the search value changes.
  • This optimization avoids recalculating the filtered list on every render, which is particularly useful for large datasets.

Output:


3. Example: Derived State using useMemo Hook

In this example, we calculate the sum of a list of numbers using useMemo. The sum is recomputed only when the list of numbers changes, not when other unrelated state changes occur.

App.js

</>
Copy
import React, { useState, useMemo } from 'react';

function SumCalculator() {
  const [numbers, setNumbers] = useState([1, 2, 3, 4, 5]);
  const [otherState, setOtherState] = useState(false);

  const sum = useMemo(() => {
    console.log('Calculating sum...');
    return numbers.reduce((total, num) => total + num, 0);
  }, [numbers]); // Recomputes only when 'numbers' changes

  const addNumber = () => {
    setNumbers([...numbers, numbers.length + 1]);
  };

  return (
    <div>
      <h2>Sum: {sum}</h2>
      <button onClick={addNumber}>Add Number</button>
      <br />
      <button onClick={() => setOtherState(!otherState)}>Toggle Other State</button>
      <p>Other State: {otherState ? 'True' : 'False'}</p>
    </div>
  );
}

export default SumCalculator;

Explanation:

  • useMemo: Calculates the sum of the array only when the numbers array changes.
  • Adding a new number updates the sum, while toggling otherState does not trigger the sum calculation.

Output:


Conclusion

The useMemo hook is a powerful tool for optimising performance in React applications. By memoizing expensive calculations, it ensures that computations are only performed when necessary. Use useMemo whenever you encounter expensive operations or components with frequent renders to keep your application efficient.