Understanding the Real Cost of useCallback in React’s Rendering Model
The first question that usually comes to mind about useCallback() is: What exactly is useCallback()?
We know that useCallback() is a React Hook used to optimize React applications. But this naturally leads to the next question: Does it actually optimize our app? If yes, how does it work under the hood?
Let’s explore how it works behind the scenes:
Most developers think useCallback = performance optimization.
But in many real-world cases, useCallback can actually make performance worse.
Let’s break it down deeply.
1. What useCallback Actually Does ->
const memoizedFun = useCallback (()=>{
doSomething(a,b)
},[a,b]);Internally React does something like:
React keeps a hook list per component (ordered by call index)
[{
memoizedState: {
callBack: memoizedFun;
dep: [a, b]
}
}]When component render First Time on the screen internally React store the memoizedFun function and store the dependency array.
if (arrDepEqual(prevDeps, currentDeps)) {
return prevCallback;
} else {
store new callBack and deps
return new callBack
}When component render Second Time on the screen internally React compares the previous dependency with current dependance array if value of dependency is changed then it create a new function and store it at a place of momoizedFun and then return a new function reference but if the value of dependency array is same then it will return previous function reference.
Important: It does NOT stop function creation.
The function is still created on every render.
React just decides whether to return the old one.
2. Why It Can Be Harmful ->
Extra memory usage & Increased comparison cost
Get Arbaz khan’s stories in your inbox
Join Medium for free to get updates from this writer.
Each useCallback:
- Stores function reference
- Stores dependency array
- Comparison dependencies on every render
If you as a senior developer wrap everything in useCallback, then you’re
- Increasing memory usage
- Increasing comparison work
- Increasing React bookkeeping
For small components → this overhead is often more expensive than recreating the function.
3. Let’s now explore when useCallback() is truly beneficial and how to use it effectively:-
useCallback Solves Only One Problem (Reference Equality)
useCallbackonly help when
- Passing function to aReact.memochild
- That child depends on function reference equality
If you’re not using React.memo, useCallback is useless.
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
<Child onClick={handleClick} />If Child is not memorized → it re-renders anyway.
So useCallback did nothing.
const Child = React.memo(({ onClick }) => {
console.log("Child render");
return <button onClick={onClick}>Click</button>;
});Important Note:
- Creating a function in JS is extremely cheap.
- Re-rendering a complex tree is expensive.
- Developers often optimize the wrong thing.








