React useCallback Hook Explained with Examples and Best Practices (2025 Guide)
- bilalshafqat42
- June 25, 2025
- React Hooks, React Js
- 0 Comments
Introduction
React’s useCallback is one of those hooks that seems confusing at first — until you start dealing with unnecessary re-renders or memoized components.
In React, functions are re-created on every render. This behavior is harmless in most cases, but when passing callbacks to deeply nested or memoized child components, re-creating the function can cause unnecessary re-renders and performance issues.
This is where useCallback shines.
In this guide, you’ll learn:
- What
useCallbackis - How it works and why it exists
- How it compares to
useMemoand inline functions - When to use it — and when not to
- Real-world use cases with code examples
What is useCallback?

useCallback is a built-in React hook that lets you memoize a function — meaning it returns the same function reference between renders unless one of its dependencies has changed.
Syntax:
const memoizedFn = useCallback(() => {
// your logic
}, [dependencies]);
If none of the dependencies change, React will return the exact same function — avoiding unnecessary function recreation and preventing extra renders in child components.
Why is this useful?
When you pass a function as a prop to a memoized child component (e.g., using React.memo), even a new function reference — with identical logic — can cause that component to re-render.
useCallback ensures that the function reference remains stable, helping with performance and preventing extra renders.
Example 1: Memoizing a Handler
import { useCallback, useState } from 'react';
function Parent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Child onClick={increment} />;
}
Without useCallback, the increment function would be re-created on every render, potentially triggering unnecessary renders in Child.
useCallback vs useMemo
Both useCallback and useMemo help with memoization — but they do different things.
| Feature | useCallback | useMemo |
|---|---|---|
| Purpose | Memoize functions | Memoize values (returned from functions) |
| Return type | A function | Any value (array, object, result) |
| Use case | Event handlers, props | Expensive calculations, filtered arrays |
Example 2: useCallback vs Inline Function
Inline Function:
<Button onClick={() => doSomething()} />
With useCallback:
const handleClick = useCallback(() => doSomething(), []);
<Button onClick={handleClick} />
In the first case, a new function is created every render.
In the second case, handleClick stays the same between renders — avoiding unnecessary re-renders of Button.
Real Use Case: Avoid Re-rendering Memoized Children
const Child = React.memo(({ onClick }) => {
console.log("Child rendered");
return <button onClick={onClick}>Click</button>;
});
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<Child onClick={handleClick} />
</>
);
}
Here, Child will NOT re-render unless handleClick changes — which it won’t, thanks to useCallback().
When to Use useCallback
- You’re passing a function as a prop to a memoized child component
- You want to avoid unnecessary function recreation
- You’re building reusable components or component libraries
- You’re using a stable callback in an effect
When NOT to Use useCallback
- Your function doesn’t affect performance when recreated
- You’re not passing it to memoized children
- Your dependencies change frequently (useCallback won’t help much)
Note: Don’t use useCallback everywhere “just in case.” It adds complexity and memory overhead. Use it when it solves a specific performance issue.
Common Mistakes with useCallback
1. Overusing it
Don’t wrap every function in useCallback by default. Only use it for actual memoization needs.
2. Missing dependencies
useCallback(() => {
doSomething(message);
}, []); // 🚫 'message' should be in dependencies
3. Using it without memoized children
If you’re not using React.memo or passing functions to children, useCallback might have no benefit.
Best Practices for useCallback (2025)
- Use with
React.memoto prevent child re-renders - Use with stable dependencies to avoid re-creating the function
- Combine with
useEffectwhen passing a callback that must not change - Profile performance with dev tools before applying
- Clean up side effects when passing memoized callbacks to useEffect
Summary: Master useCallback to Improve React Performance
useCallback is not just a “nice to have” — it’s essential when building performant React apps with lots of components or heavy rendering logic.
Remember:
- It returns a memoized version of your function
- It helps avoid unnecessary re-renders
- It should be used selectively — not everywhere
If you work with React.memo, nested components, or reusable hooks — useCallback is your best friend.

