Dung (Donny) Nguyen

Senior Software Engineer

useMemo

useMemo is a React Hook that lets us cache the result of an expensive calculation between renders. Instead of recomputing a value on every render, React remembers (memoizes) the last computed value and only recalculates it when one of its dependencies changes. This helps avoid unnecessary work and keeps our components fast.

Syntax

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

Why Use useMemo?

On every render, React runs our component function from top to bottom. Any calculation inside the body runs again, even if its inputs did not change. For cheap operations this is fine, but for expensive computations—or values passed to memoized children—recomputing every time can hurt performance. useMemo solves this by reusing the previous result when the inputs are the same.

Example: Caching an Expensive Calculation

import { useMemo, useState } from 'react';

function ProductList({ products }) {
  const [query, setQuery] = useState('');

  // Only re-runs when `products` or `query` changes.
  const filteredProducts = useMemo(() => {
    console.log('Filtering products...');
    return products.filter((product) =>
      product.name.toLowerCase().includes(query.toLowerCase())
    );
  }, [products, query]);

  return (
    <div>
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search products"
      />
      <ul>
        {filteredProducts.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
}

Without useMemo, the filtering would run on every render—including renders triggered by unrelated state changes. With useMemo, it only re-runs when products or query actually changes.

Example: Keeping a Stable Reference for Memoized Children

useMemo is also useful when we pass objects or arrays to child components wrapped in React.memo. Since these are recreated on every render, a memoized child would re-render anyway unless we keep the reference stable.

import { useMemo } from 'react';

function Dashboard({ userId }) {
  const config = useMemo(
    () => ({ userId, theme: 'dark' }),
    [userId]
  );

  return <Chart config={config} />;
}

Here, config keeps the same reference between renders as long as userId stays the same, preventing needless re-renders of Chart.

useMemo vs useCallback

Both hooks memoize something between renders, but they cache different things:

Hook Caches Returns
useMemo The result of calling a function A memoized value
useCallback The function itself A memoized function

In fact, useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

Best Practices

Conclusion

useMemo helps us avoid recalculating expensive values and keeps object and array references stable across renders. Used thoughtfully—only where it provides a measurable benefit—it is a valuable tool for optimizing React applications without changing what our components render.