JAVASCRIPT
Memoizing Function References with `useCallback` for Performance
Optimize React component rendering by using `useCallback` to memoize event handlers and functions, preventing unnecessary re-renders of child components.
import React, { useState, useCallback, memo } from 'react';
// A child component that will only re-render if its props change
const ExpensiveComponent = memo(({ onClick, value }) => {
console.log('ExpensiveComponent rendered');
return (
<div style={{ border: '1px dashed gray', padding: '10px', margin: '10px' }}>
<p>Value: {value}</p>
<button onClick={onClick}>Increment from Child</button>
</div>
);
});
function ParentComponent() {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
// This function reference will change on every re-render of ParentComponent
// const handleClickWithoutCallback = () => {
// setCount(prevCount => prevCount + 1);
// };
// This function reference will only change if `setCount` changes (which it won't)
// or if dependencies in the array change.
const handleClickWithCallback = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []); // Empty dependency array means this function is memoized once
console.log('ParentComponent rendered');
return (
<div>
<h1>Parent Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment Parent Count</button>
<button onClick={() => setOtherState(otherState + 1)}>
Change Other State ({otherState})
</button>
<hr />
<ExpensiveComponent onClick={handleClickWithCallback} value={count} />
{/*
If using handleClickWithoutCallback, ExpensiveComponent would re-render
even when only otherState changes, because its 'onClick' prop
would be a new function reference each time.
*/}
</div>
);
}
export default ParentComponent;
How it works: The `useCallback` hook is used to memoize functions. When passed a function and a dependency array, it returns a memoized version of the callback that only changes if one of the dependencies has changed. This is particularly useful when passing callbacks to optimized child components (e.g., those wrapped in `React.memo`), as it prevents unnecessary re-renders of those children by ensuring the prop's reference remains stable across parent renders.