Premature optimization is a cost
React.memo, useMemo and useCallback are not free: each one stores
values in memory and compares dependencies on every render. If you apply them to
everything "just in case", you add complexity and sometimes even worsen the
performance.
"Premature optimization is the root of all evil." — Donald Knuth
Measure first
The golden rule: measure before optimizing. Don't optimize based on hunches. Tools to measure:
- React DevTools → Profiler tab: shows which components re-render and how long they take.
- The render highlighting ("highlight updates") to visually see what repaints.
performance.now()to time specific computations.
When SHOULD you optimize?
- The Profiler shows a slow component that re-renders frequently.
- A truly expensive computation (sorting/filtering thousands of elements) runs on every render.
- A long list repaints entirely when a single element changes.
When NOT?
- Small and cheap components: memoizing them adds nothing.
- Before having a measurable problem. If you don't notice slowness, don't invent it.
- As an automatic habit on every component: it clutters the code with no benefit.
Better than memoizing: reduce the work
Often the best optimization is not memo, but changing the structure:
- Lift the state only as far as needed and push down the components that don't depend on it, so they don't re-render.
- Pass content as
childrenso it isn't recreated. - Split large components into smaller, more focused pieces.
Correct order: 1) write clear code, 2) measure if there's a real problem, 3) optimize only what the Profiler points out, 4) measure again to confirm the improvement.