React useCallback Hook
25 April 2025 | Category: React Js
What is useCallback
?
In simple terms:
useCallback
is a React Hook that memorizes a function, so it doesn’t get recreated on every render – unless its dependencies change.
This helps prevent unnecessary re-renders and improves performance when passing functions to child components.
📦 When to use useCallback
You’ll want to use useCallback
when:
✅ You’re passing functions as props to child components
✅ Your component re-renders often and causes unnecessary updates
✅ You want to optimize performance in large React apps
🔧 Syntax
const memoizedFunction = useCallback(() => {
// function logic
}, [dependencies]);
- Returns a memoized version of the callback function
- Only changes if dependencies in the array change
📌 Real Life Analogy
Imagine you’re a chef and your helper asks for your signature sauce recipe every time you cook. Without useCallback
, you rewrite it every time. With useCallback
, you just save the recipe once and reuse it unless the ingredients change!
✅ Basic Example
import React, { useState, useCallback } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount((prev) => prev + 1);
}, []);
return (
<div>
<h2>Count: {count}</h2>
<button onClick={increment}>Increment</button>
</div>
);
}
🔍 Even though increment
looks simple, useCallback
ensures the function stays the same across renders unless dependencies change.
🤖 When useCallback
Shines – Child Components
Let’s see how useCallback
helps prevent unnecessary re-renders of child components.
✅ Without useCallback
(inefficient)
function Child({ onClick }) {
console.log('Child rendered');
return <button onClick={onClick}>Click me</button>;
}
export default function App() {
const [count, setCount] = useState(0);
const handleClick = () => {
console.log('Clicked');
};
return (
<>
<button onClick={() => setCount(count + 1)}>Re-render Parent</button>
<Child onClick={handleClick} />
</>
);
}
Even when clicking the parent button, the child re-renders every time because handleClick
is recreated on every render.
✅ With useCallback
(optimized)
import React, { useState, useCallback } from 'react';
const Child = React.memo(({ onClick }) => {
console.log('Child rendered');
return <button onClick={onClick}>Click me</button>;
});
export default function App() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Clicked');
}, []);
return (
<>
<button onClick={() => setCount(count + 1)}>Re-render Parent</button>
<Child onClick={handleClick} />
</>
);
}
🔍 Now, the Child
component won’t re-render unless handleClick
actually changes (which it won’t, thanks to useCallback
).
📋 Summary Table
Concept | Description |
---|---|
useCallback | Memoizes a function |
Prevents | Recreating function on every render |
Use case | When passing functions to memoized children |
Dependencies | Function will update only when these change |
⚠️ Common Mistakes
- Overusing
useCallback
: Don’t use it everywhere. Only when necessary (especially withReact.memo
). - Missing dependencies: Always list the correct dependencies or use ESLint to warn you.
- Confusing with
useMemo
:useMemo
→ memoize a valueuseCallback
→ memoize a function
🔥 Real World Use Cases
- Avoiding re-renders in
React.memo
child components - Stable event handlers for optimized animations
- Efficient callbacks in custom hooks