🎯 React.memo, useCallback, useMemo
reactadvanced

🎯React.memo, useCallback, useMemo

Three tools to prevent unnecessary re-renders: React.memo (component), useCallback (function), useMemo (value). All use reference equality and shallow comparison.

Memory Trick

memo=component, useCallback=function, useMemo=value. Memoize what changes your children's references.

Track completion, mastery, and revision.

1️⃣ The Three Tools

ToolWhat it memoizesReturns
React.memoComponent outputSame JSX if props unchanged
useCallbackFunction referenceSame function if deps unchanged
useMemoComputed valueCached value if deps unchanged
js
// React.memo — skip re-render if props shallow-equal const Child = React.memo(({ count }) => <p>{count}</p>); // useCallback — stable function reference const handleClick = useCallback(() => { ... }, [deps]); // useMemo — expensive calculation const sorted = useMemo(() => data.sort(compareFn), [data]);

2️⃣ When to Actually Use Them

Use memo/useCallback/useMemo when:

  • Child is in a React.memo wrapper and you pass functions/objects as props
  • Computation is genuinely expensive (large sort, filter, etc.)
  • Stable reference is required (dependency of useEffect)

Don't use when:

  • Component renders quickly anyway (adds overhead)
  • Props change on every render (memo comparison is wasted)
  • Premature optimization (profile first!)

Rule: Optimize after you measure, not before.

3️⃣ Why Shallow Comparison?

React uses shallow (reference) equality:

js
// Every render creates new reference — memo fails <Child onClick={() => doThing()} data={{value: 1}} /> // Stable references — memo works const onClick = useCallback(() => doThing(), []); const data = useMemo(() => ({value: 1}), []); <Child onClick={onClick} data={data} />

Deep comparison would be more expensive than the re-render itself.

Was this helpful?

Test your Knowledge

2 questions to cement what you just learned.