Stop 16 · PerformanceTopics · 3/13

Memoization

Part of the Frontend Developer Roadmap

In short

Memoization means remembering a result so you don't calculate it again. In React, it can stop slow work and needless re-renders, but used everywhere it just adds clutter.

Using `useMemo`/`useCallback`/`React.memo` (or non-React memoization) to skip expensive recalculations and re-renders — a targeted performance tool, not a default habit.

The jaadu copies a solved answer from a neat notebook instead of solving it again.

Think of it like this

Your formula notebook

Before exams, you write solved answers in a notebook. When the same question comes up again, you copy the answer instead of solving it from scratch. If the question changes, you solve it fresh. That's memoization.

Watch it happen

Adding to the cart, with memo in place

setCart
Shop renders
useMemo
useCallback
memo check

1/5The user adds an item. setCart updates the cart state.

The big ideas

What you need to know

useMemo remembers a value

It reruns the calculation only when a dependency changes. Useful for heavy work like filtering 10,000 items.

useCallback remembers a function

It keeps the same function reference between renders, which matters when passing it to a memo child.

memo skips re-renders

React.memo wraps a component so it re-renders only when its props actually change.

React Compiler can do it for you

The React Compiler adds memoization automatically at build time. If your project uses it, you'll need far fewer manual hooks.

See it in code

Walk through the code

tsx
1import { memo, useCallback, useMemo, useState } from "react";2 3const ProductList = memo(function ProductList({ items, onAdd }: Props) {4  return items.map((p) => <button key={p.id} onClick={() => onAdd(p.id)}>{p.name}</button>);5});6 7export function Shop({ products }: { products: Product[] }) {8  const [query, setQuery] = useState("");9  const [cart, setCart] = useState<string[]>([]);10  const visible = useMemo(11    () => products.filter((p) => p.name.toLowerCase().includes(query.toLowerCase())),12    [products, query],13  );14  const onAdd = useCallback((id: string) => setCart((c) => [...c, id]), []);15  // ...render input, cart count and <ProductList items={visible} onAdd={onAdd} />16}

1/3memo wraps ProductList so it only re-renders when its props change.

Adding to the cart re-renders Shop, but ProductList skips re-rendering because visible and onAdd keep the same references.

Save yourself the pain

Common mistakes

Oops

Wrapping every value in useMemo 'for performance'.

Do this instead

Measure first with the React DevTools Profiler. Memoize only what's actually slow.

Oops

Wrapping a child in memo but passing it a new inline object or function each render.

Do this instead

memo compares props by reference. Memoize those props too, or memo does nothing.

Your mission

Catch a wasted render

~30 min

Quick check

You wrapped a child in React.memo, but it still re-renders on every parent render. What's the likely cause?

Go deeper

  1. 1Profile a component with React DevTools before adding any memoization.
  2. 2Add memoization only where the profiler shows an actual cost.
  3. 3Learn that overusing memoization can add complexity without measurable benefit.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge