Wrapping Components with React.memo

Practice wrapping components with React.memo and watching which re-renders disappear — and which ones don't.

March 22, 20262 min read4 / 5

Reading about memoization is one thing. Watching the render highlights and seeing which components stop flashing — that's when it actually clicks.

This exercise puts you in a realistic scenario: a parent component with multiple children, some of which need their re-renders reduced. Your job is to apply React.memo, useCallback, and useMemo in the right places and watch the behavior change.

What You'll Practice

The setup is a dashboard with a filter bar and a list of cards. The filter state lives in the parent. Every time it changes, the whole tree re-renders — including cards that don't care about the filter at all.

The problem: Some components re-render on every filter change even when their props haven't changed. The re-render highlights make this obvious.

The goal: Eliminate the unnecessary re-renders by applying memoization correctly — but only where it makes a measurable difference.

Key Things to Notice

As you work through the exercise, pay attention to a few patterns:

React.memo alone isn't enough for function props. If you wrap a child in memo but the parent passes an inline function, the function reference changes every render → memo's comparison fails → child still re-renders.

The fix requires two pieces working together. memo on the child + useCallback for the function prop passed to it. Neither works without the other in this case.

Not every component needs to be memoized. Some re-renders are fast and expected. The goal isn't zero re-renders — it's eliminating renders where the output can't possibly have changed.

The Pattern at a Glance

TSX
// Before — FilterCard re-renders on every parent state change function Dashboard() { const [filter, setFilter] = useState('all'); const handleChange = (value) => setFilter(value); // new fn every render return ( <> <FilterBar onChange={handleChange} /> {/* re-renders even if filter UI hasn't changed */} <StatsSummary /> {/* doesn't use filter — but still re-renders */} </> ); } // After — only the components that actually changed update const FilterBar = memo(function FilterBar({ onChange }) { /* ... */ }); const StatsSummary = memo(function StatsSummary() { /* ... */ }); function Dashboard() { const [filter, setFilter] = useState('all'); const handleChange = useCallback((value) => setFilter(value), []); return ( <> <FilterBar onChange={handleChange} /> {/* stable reference → memo works */} <StatsSummary /> {/* no props → memo always skips it */} </> ); }

Try the exercise below. The render count on each component tells you exactly what's happening.

Practice what you just read.

Wrap Components with React.memo
1 exercise

Enjoyed this? Get more like it.

Deep dives on system design, React, web development, and personal finance — straight to your inbox. Free, always.