React useCallback
useCallback caches a function reference between renders until one of its dependencies changes. It is mainly useful when function identity affects memoization or dependency comparisons; it does not automatically make the function's work faster.
In React, a component creates new function objects when it renders. `useCallback` lets React retain a function reference and return that same reference on later renders while its dependency values remain unchanged.
The hook takes a function and a dependency array: `useCallback(fn, dependencies)`. React compares each dependency with its previous value using `Object.is`. When the dependencies have not changed, the previously stored function reference is returned; otherwise React stores and returns the new function.
The main reason to use `useCallback` is referential equality. For example, a memoized child receiving a callback as a prop can avoid a render when the callback reference stays stable. It can also prevent an effect or another hook from repeatedly reacting to a changing function dependency.
`useCallback` does not memoize the function's return value. If the goal is to cache an expensive calculation, `useMemo` is the related hook. Also, adding `useCallback` everywhere can make code harder to read without producing a measurable benefit, so its use should be driven by a real dependency or rendering concern.
Key points
- `useCallback` memoizes a function reference, not its result.
- The cached reference is reused until a dependency changes.
- Dependencies are compared with `Object.is`.
- Stable callback identity can help `memo`-optimized children skip renders.
- Use it when function identity matters, not simply because a component contains a function.
Interview questions
What problem does useCallback solve?
`useCallback` provides a stable function reference across renders when its dependencies have not changed. This matters because JavaScript creates a new function object when a function expression is evaluated during a render. Stable identity can prevent unnecessary work in consumers that compare references, such as memoized child components. It should be used when that identity has a practical consequence rather than as a default optimization.
How does the dependency array affect useCallback?
React compares the listed dependencies with their previous values using `Object.is`. If all dependencies are unchanged, React can return the previously stored function reference. If any dependency changes, React returns the newly provided function. Every reactive value used by the callback that must reflect current rendering state should be considered when determining the dependencies.
Does useCallback improve the performance of the function itself?
No. `useCallback` does not make the callback's body execute faster. Its primary effect is stabilizing the function reference between renders. That stable identity can reduce downstream rendering or repeated hook work when another component or hook compares the callback by reference. The optimization is therefore about identity and surrounding work, not the callback's execution speed.
How does useCallback work with React.memo?
A memoized child can compare incoming props and skip rendering when its relevant props remain equal. Without `useCallback`, a parent that creates an inline callback on every render may pass a new function reference even when the callback's behavior is effectively unchanged. `useCallback` can keep that prop reference stable until dependencies change. This only helps if the child is actually memoized and the callback prop is one of the values affecting its comparison.
What are common alternatives to useCallback when a callback has state dependencies?
One option is to use a functional state updater when the callback only needs the previous state value. For example, `setCount(c => c + 1)` avoids requiring the current `count` value to be captured by the callback. Another option is to move the function closer to where it is used, which can remove the need for cross-render identity altogether. The right choice depends on why the callback needs to be stable.