Performance
useMemo & useCallback (and when not to)
Referential stability, real costs, and profiling before optimizing.
useMemo caches a computed value; useCallback caches a function identity across renders. Their main job is preserving referential equality so memoized children and effect dependencies do not needlessly re-run.
Memoization is keeping last week’s receipt: reuse the total if nothing changed — but do not file receipts for a 20-cent purchase.
Key concepts
1
They are not free: React stores the value and compares deps every render. Wrapping trivial calculations often costs more than it saves.
2
Reach for them when: a child is wrapped in memo and receives a callback/object, a value feeds a useEffect dependency array, or a computation is genuinely expensive. Measure with the Profiler first.
Measure with the Profiler first.memouseEffect
3
Pitfall: memoizing everything "just in case," adding complexity and memory for no gain. Interview angle: "does useMemo guarantee the value is cached?" — no; React may discard it, so never rely on it for correctness, only performance.
Pitfall:Interview angle:
jsx
const sorted = useMemo(
() => [...rows].sort((a, b) => a.price - b.price),
[rows],
);
const onSelect = useCallback((id) => dispatch({ type: 'select', id }), [dispatch]);
<Row data={sorted} onSelect={onSelect} /> // stable props keep memo(Row) from re-rendering