How to Implement useMemo Hook in React

This article provides a straightforward guide on how to implement the useMemo Hook in React to optimize application performance. You will learn what useMemo is, when to use it to prevent unnecessary calculations during re-renders, and how to write the code with a practical step-by-step example.

Understanding useMemo

The useMemo Hook is a built-in React Hook that caches (memoizes) the result of a calculation between renders. In React, whenever a component’s state or props change, the entire component re-renders, re-running all functions inside it. If you have an expensive calculation, running it on every render can slow down your application. useMemo solves this by only recalculating the value when one of its dependencies changes.

Basic Syntax

The useMemo Hook accepts two arguments: a function that returns the value you want to cache, and an array of dependencies.

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

Step-by-Step Implementation

Here is a practical example of how to implement useMemo in a React component. In this example, we have a component with a heavy filtering operation and an unrelated counter button.

1. Import useMemo

First, import the Hook from the React library.

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

2. Define the Component and State

Set up your component with the necessary state. We will have a list of items, a search query, and an unrelated counter state.

function SearchComponent() {
  const [query, setQuery] = useState('');
  const [count, setCount] = useState(0);

  const items = ['Apple', 'Banana', 'Orange', 'Mango', 'Pineapple', 'Grapes'];

3. Implement useMemo for the Expensive Calculation

Without useMemo, the filtering logic would run every time you click the counter button. By wrapping the filtering logic in useMemo, it only runs when the query or items change.

  const filteredItems = useMemo(() => {
    console.log('Filtering items...'); // This will only log when "query" changes
    return items.filter(item => item.toLowerCase().includes(query.toLowerCase()));
  }, [query]); // Only recalculate if "query" changes

4. Render the Output

Complete the component by returning the JSX.

  return (
    <div>
      <input 
        type="text" 
        value={query} 
        onChange={(e) => setQuery(e.target.value)} 
        placeholder="Search fruits..."
      />
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>

      {/* Clicking this button triggers a re-render, but does not re-run the filtering logic */}
      <button onClick={() => setCount(count + 1)}>
        Renders: {count}
      </button>
    </div>
  );
}

export default SearchComponent;

When to Use useMemo

You should not wrap every calculation in useMemo, as the Hook itself has a small performance overhead. Use it in the following scenarios: