Building Your Learning Module...
Getting things ready for you!
Find videos you like?
Save to resource drawer for future reference!
useCallback returns a memoized callback function. It caches a function between re-renders until its dependencies change, preventing child components from re-rendering unnecessarily.
Child components re-render even if nothing changed!
Child components don't re-render unnecessarily!
First, import useCallback from React at the top of your component file.
Pro Tip
You can import multiple hooks: { useState, useEffect, useCallback }.
Wrap your callback function with useCallback to memoize it.
Key Point
The function will only be recreated if dependencies in the array change!
Include variables that your function depends on in the dependency array.
Important
Use functional updates (setCount(prev => prev + 1)) when possible to avoid dependencies!
Pass the memoized callback to child components for optimal performance.
Key Point
Combine useCallback with React.memo for maximum performance optimization!
Child component only re-renders when necessary
function Parent() {
const [count, setCount] = React.useState(0);
const [name, setName] = React.useState('React');
// Memoized callback - same function instance!
const increment = React.useCallback(() => {
setCount(c => c + 1);
}, []); // Empty deps - never changes
// This callback depends on 'name'
const greet = React.useCallback(() => {
alert(`Hello, ${name}!`);
}, [name]); // Recreated when name changes
return (
<div className="container">
<h1>🚀 useCallback Demo</h1>
<div className="controls">
<div className="input-group">
<label>Name:</label>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your name"
/>
</div>
<div className="stats">
<div className="stat">
<div className="label">Count</div>
<div className="value">{count}</div>
</div>
</div>
<div className="buttons">
<button onClick={increment} className="btn-primary">
Increment Count
</button>
<button onClick={greet} className="btn-secondary">
Greet Me
</button>
</div>
</div>
<div className="children">
<ChildCounter count={count} onIncrement={increment} />
<ChildGreeter name={name} onGreet={greet} />
</div>
<div className="info">
💡 Child components only re-render when their props actually change!
</div>
</div>
);
}
// Memoized child components
const ChildCounter = React.memo(function ChildCounter({ count, onIncrement }) {
const renders = React.useRef(0);
renders.current += 1;
return (
<div className="child">
<h3>🔢 Counter Child</h3>
<p>Count: <strong>{count}</strong></p>
<p>Renders: <strong>{renders.current}</strong></p>
<button onClick={onIncrement} className="btn-child">
Increment
</button>
</div>
);
});
const ChildGreeter = React.memo(function ChildGreeter({ name, onGreet }) {
const renders = React.useRef(0);
renders.current += 1;
return (
<div className="child">
<h3>👋 Greeter Child</h3>
<p>Name: <strong>{name}</strong></p>
<p>Renders: <strong>{renders.current}</strong></p>
<button onClick={onGreet} className="btn-child">
Greet
</button>
</div>
);
});
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Parent />);Loading preview...
Returns same function instance between renders until dependencies change.
Child components with React.memo won't re-render if callback hasn't changed.
Function is recreated only when dependencies in the array change.
Don't use everywhere! Only when needed for performance optimization.