The useCallback() Hook memoizes functions in React so the same function reference is reused between renders unless dependencies change.
React.memo()
// Basic useCallback syntax
const memoizedCallback = useCallback(() => {
console.log("Callback executed");
}, [dependency]);
// New function created on every render
function Parent() {
const [count, setCount] = React.useState(0);
const handleClick = () => {
console.log("Clicked");
};
return (
<div>
<Child onClick={handleClick} />
<button onClick={() => setCount(count + 1)}>
Increment ({count})
</button>
</div>
);
}
const Child = React.memo(({ onClick }) => {
console.log("Child rendered");
return <button onClick={onClick}>Child</button>;
});
// Stable function reference using useCallback
function Parent() {
const [count, setCount] = React.useState(0);
const handleClick = React.useCallback(() => {
console.log("Clicked");
}, []);
return (
<div>
<Child onClick={handleClick} />
<button onClick={() => setCount(count + 1)}>
Increment ({count})
</button>
</div>
);
}
const Child = React.memo(({ onClick }) => {
console.log("Child rendered");
return <button onClick={onClick}>Child</button>;
});
// Function recreated only when dependency changes
function Counter() {
const [count, setCount] = React.useState(0);
const [step, setStep] = React.useState(1);
const increment = React.useCallback(() => {
setCount(c => c + step);
}, [step]);
return (
<div>
<h4>Count: {count}</h4>
<button onClick={increment}>+{step}</button>
<input
type="number"
value={step}
onChange={e => setStep(Number(e.target.value))}
/>
</div>
);
}
// useCallback + React.memo optimization
const List = React.memo(({ items, onSelect }) => {
return (
<ul>
{items.map(item => (
<li key={item} onClick={() => onSelect(item)}>
{item}
</li>
))}
</ul>
);
});
function App() {
const [selected, setSelected] = React.useState(null);
const items = ["Apple","Banana","Cherry"];
const handleSelect = React.useCallback(item => {
setSelected(item);
}, []);
return (
<div>
<List items={items} onSelect={handleSelect} />
<p>Selected: {selected || "None"}</p>
</div>
);
}
Click the buttons to see output below
// Simulating function recreation vs memoization (UI output)
let memoizedFn;
let recreateCount = 0;
document.getElementById("recreateBtn").addEventListener("click", () => {
recreateCount++;
const newFn = () => "New function created";
document.getElementById("demoOutput").textContent =
"Recreated Function Count: " + recreateCount + " → " + newFn();
});
document.getElementById("memoBtn").addEventListener("click", () => {
if (!memoizedFn) {
memoizedFn = () => "Same memoized function reused";
}
document.getElementById("demoOutput").textContent =
"Memoized Function → " + memoizedFn();
});
useCallback