JAVASCRIPT
Optimize Component Performance with useCallback
Understand how to use React's useCallback hook to memoize event handler functions, preventing unnecessary re-renders of child components and improving application performance.
import React, { useState, useCallback } from 'react';
// A simple child component that re-renders if its props change
const Button = React.memo(({ onClick, label }) => {
console.log(`Rendering Button: ${label}`);
return <button onClick={onClick}>{label}</button>;
});
function ParentComponent() {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
// This function reference changes on every render of ParentComponent
const handleClickWithoutCallback = () => {
setCount(prevCount => prevCount + 1);
};
// This function reference is stable unless 'count' changes
// (in this specific example, 'count' is not used inside, so it could be [])
// We use useCallback to memoize the function reference.
const handleClickWithCallback = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []); // Empty dependency array means this callback is memoized once and never changes.
const handleOtherStateChange = useCallback(() => {
setOtherState(prev => prev + 1);
}, []);
console.log('Rendering ParentComponent');
return (
<div>
<h1>useCallback for Performance</h1>
<p>Count: {count}</p>
<p>Other State: {otherState}</p>
<h2>Without useCallback:</h2>
{/* This button will re-render even if its label and the logic of handleClickWithoutCallback haven't changed, because a new function reference is created on every ParentComponent render. */}
<Button onClick={handleClickWithoutCallback} label="Increment Count (No Callback)" />
<h2>With useCallback:</h2>
{/* This button will only re-render if its props (onClick in this case) actually change. Since handleClickWithCallback is memoized, the Button component (wrapped in React.memo) avoids unnecessary re-renders. */}
<Button onClick={handleClickWithCallback} label="Increment Count (With Callback)" />
<button onClick={() => setOtherState(otherState + 1)} style={{marginTop: '20px'}}>
Change Other State (Triggers Parent re-render)
</button>
</div>
);
}
export default ParentComponent;
How it works: The `useCallback` hook is a performance optimization tool in React. It memoizes a function definition, preventing it from being re-created on every render unless its dependencies change. In this example, `handleClickWithCallback` is memoized with an empty dependency array, ensuring its reference remains stable. When passed to `React.memo`-wrapped child components like `Button`, this stable reference prevents the child from re-rendering unnecessarily when the parent component re-renders but the callback's logic or dependencies haven't changed, thus improving application performance by reducing rendering overhead.