Skip to content

Part 7.4 — Performance Hooks: useMemo, useCallback & useDeferredValue

Site Console Site Console
3 min read Updated Feb 3, 2026 Frontend Design 0 comments

Performance problems in React rarely come from missing useMemo.
They come from unclear boundaries, unnecessary re-renders, and incorrect state placement.

Performance hooks are tools of last resort—not default patterns. This post shows you how to reason about them calmly and apply them only when they provide measurable value.


1. First Rule: Measure Before You Optimize

Before touching a performance hook, ask:

  • is this component actually slow?

  • does it re-render often?

  • is the work expensive?

If you can’t answer yes to at least one, don’t optimize.

React is already fast by default.


2. Understanding Re-Renders (Quick Reality Check)

A component re-renders when:

  • its state changes

  • its props change

  • its parent re-renders

Re-renders are not bugs. They are normal.

Performance issues arise when re-renders do expensive work.


3. useMemo: Cache Expensive Computation

useMemo caches a calculated value, not a render.

Example:

const filteredUsers = React.useMemo(() => {
  return users.filter(u => u.active);
}, [users]);

Use useMemo when:

  • computation is expensive

  • inputs are stable

  • result is reused

Don’t use it for:

  • simple mapping

  • trivial calculations

  • “just in case” optimization


4. Common useMemo Mistake

Bad:

const value = useMemo(() => ({ a, b }), [a, b]);

If you don’t pass this object to memoized children, useMemo is wasted.

Memoization without a consumer is noise.


5. useCallback: Stabilize Function References

useCallback memoizes a function identity.

const onSubmit = React.useCallback(() => {
  save(data);
}, [data]);

This matters only when:

  • function is passed to a memoized child

  • child relies on reference equality

If neither is true, skip it.


6. The Most Common useCallback Anti-Pattern

This is everywhere—and mostly useless:

const handleClick = useCallback(() => {
  setOpen(true);
}, []);

If:

  • component is small

  • handler is not passed down

  • child isn’t memoized

Then useCallback adds complexity without benefit.


7. Memoization Works in Pairs

Memo hooks only matter when paired with React.memo.

Example:

const ListItem = React.memo(function ListItem({
  item,
  onSelect,
}: Props) {
  return <li onClick={() => onSelect(item.id)}>{item.name}</li>;
});

Now useCallback on onSelect actually matters.

Without React.memo, it doesn’t.


8. Avoid Blanket Memoization

This pattern is a smell:

const Component = React.memo(() => {
  const handler = useCallback(...)
});

This often indicates:

  • unclear re-render cause

  • state placed too high

  • unnecessary abstraction

Fix architecture first.


9. useDeferredValue: Improving Perceived Performance

useDeferredValue lets React delay low-priority updates.

Example: filtering a large list while typing.

const deferredQuery = useDeferredValue(query);
const results = filterItems(items, deferredQuery);

Result:

  • input stays responsive

  • list updates slightly later

This improves UX without complex logic.


10. When useDeferredValue Is Appropriate

Use it when:

  • UI must remain responsive

  • updates are visually expensive

  • slight delay is acceptable

Common cases:

  • search-as-you-type

  • large tables

  • heavy charts

Do not use it to hide architectural problems.


11. Performance Hooks Do Not Fix Bad State Placement

No hook will fix:

  • global state overuse

  • massive contexts

  • unnecessary provider re-renders

  • deep prop drilling

If performance feels hard, revisit:

  • state boundaries

  • ownership

  • component responsibilities

Optimization follows architecture.


12. Debugging Performance Correctly

Use:

  • React DevTools Profiler

  • component highlight updates

  • logging render counts

Don’t guess. Measure.


13. A Practical Decision Checklist

Before using a performance hook, confirm:

  • the component re-renders frequently

  • the work inside render is expensive

  • props/state change less frequently

  • simpler refactors won’t solve it

If all four are true, optimize.


14. Summary

You now know how to:

  • reason about re-renders calmly

  • use useMemo for real computation

  • use useCallback only when identity matters

  • pair memoization correctly

  • use useDeferredValue for perceived performance

  • avoid premature optimization traps

Related

Leave a comment

Sign in to leave a comment.

Comments