Wrapping Components with React.memo
Practice wrapping components with React.memo and watching which re-renders disappear — and which ones don't.
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
// 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.
Keep reading
Enjoyed this? Get more like it.
Deep dives on system design, React, web development, and personal finance — straight to your inbox. Free, always.