useCallback
React chapter 13 · useCallback · useEventCallback · source: react.dev/reference/react/useCallback
The problem
The row is wrapped in memo and its text never changes, but the parent passes onAdd={() => ...} inline. A function written in the body is a new function every render, so memo sees a change.
The pattern that fixes it
useCallback(fn, deps) hands back the same function until its dependencies change. Use the state updater form so the function needs no dependencies and stays stable forever.
In plain words
A function you write inside a component is created again on every render. To React, the new copy is a different thing from the old one, even if the code is identical. useCallback keeps the old copy.
Every morning you hand each cashier a freshly printed copy of the same instruction sheet. They think the rules changed and stop to re-read it. useCallback gives them the same sheet until the rules really change.
Terms
- callback
- A function you pass to a child so the child can tell the parent something happened, like onAdd.
- closure
- A function remembers the variables from the render where it was created. An old function remembers old values.
- updater function
- Passing setCart(c => [...c, id]) instead of a value. React supplies the latest state, so you do not need to read cart yourself.
Going deeper
How does it work?
useCallback(fn, deps) is the same as useMemo(() => fn, deps). On each render React compares the dependency list with last time using Object.is. If nothing changed it returns the stored function, otherwise it stores and returns the new one. A memoized child then sees the same prop and skips rendering.
When it does nothing, or goes wrong
It does nothing if the child is not wrapped in memo, because the child re-renders anyway. Putting cart in the deps keeps the function correct but makes it change on every cart update (try it in the lab). Leaving cart out while reading it gives a stale closure: the function keeps using the cart from the first render. The updater form setCart(c => ...) avoids both problems.
When NOT to use it, and modern alternatives
useCallback itself makes nothing faster; it only matters when something compares function identity (a memo child, an effect dependency). Do not wrap every handler. When a handler must always see the latest values without changing identity, use useEffectEvent (or MUI useEventCallback), covered in chapter 15. The React Compiler memoizes handlers automatically, so most manual useCallback calls can go.
Keep learning
- Previous: useMemo
- Next: Custom hooks
- Related: memo
- Related: useMemo
- Related: Custom hooks
- Related: useEffectEvent
- Related: useTransition
- Related: useDeferredValue
More courses
- Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
- Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
- Database in depth — How a query becomes work. Indexes, isolation, locks, and the plans that explain why a page is slow — not an ORM tour.
- System Design — Eight interview case studies, from a flash sale and Tatkal to a live final and a chat model, plus JWT in separate chapters.
- Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
- Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
- Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
- CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
- Accessibility — HTML labs first, then a full pass of WAI-ARIA 1.3: naming, every state, widget and structure roles, live regions, ariaNotify, and relationships.
- Docker — What an image is, why layers cache, and how containers find each other on a network.
- Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.