Understanding when to use these optimization tools is crucial for React performance. Here's a comprehensive guide.
React.memo Basics#
useCallback Basics#
useMemo Basics#
When NOT to Use These#
When TO Use These#
Common Patterns#
Fixing Common Mistakes#
Performance Testing#
Decision Flowchart#
Should I use React.memo?
├── Is the component expensive to render? → Consider memo
├── Does parent re-render often with same props? → Consider memo
├── Are all props primitives? → memo works easily
└── Has functions/objects as props? → Need useCallback/useMemo too
Should I use useCallback?
├── Is the callback passed to memoized child? → Yes
├── Is the callback used in dependency array? → Yes
├── Is the callback just used locally? → Probably not
└── Is child not memoized? → Probably not
Should I use useMemo?
├── Is the computation expensive? → Yes
├── Is the result used in dependency array? → Yes
├── Is it creating objects for memoized children? → Yes
├── Is it simple math/string ops? → Probably not
└── Is it just JSX creation? → Probably not
Best Practices#
General:
✓ Measure before optimizing
✓ Use React DevTools Profiler
✓ Understand the render cascade
✓ Start without optimization
React.memo:
✓ Use for pure components
✓ Combine with useCallback for handlers
✓ Consider custom comparator for complex props
✓ Don't use for frequently changing props
useCallback:
✓ Use when passed to memoized children
✓ Use when in dependency arrays
✓ Include all dependencies
✓ Use updater functions to reduce deps
useMemo:
✓ Use for expensive computations
✓ Use to maintain referential equality
✓ Don't overuse for simple operations
✓ Consider moving computation outside
Conclusion#
React.memo, useCallback, and useMemo are powerful but often misused. Use them when there's a measurable performance benefit: expensive computations, preventing unnecessary re-renders of memoized children, or maintaining referential equality for effects. Always measure first, and avoid premature optimization.