Core role
useCallback
is a performance optimization hook for React forCache function references。
Its core value isAvoid invalid rendering of child components due to function reference changes when parent component is re-rendered。
What problems are solved?
-
Problem scenario:
When the parent component passes a function to the child component, if the parent component updates, the function will be recreated each time. Even if subcomponents are usedPackage will also trigger re-rendering due to different function references.
-
Optimization goals:
Keep function references unchanged unless the dependencies change, thereby reducing invalid rendering of subcomponents.
Problem scenario:
// Parent component
const Parent = () => {
const [count, setCount] = useState(0);
// Every time Parent renders, a new handleClick function is created
const handleClick = () => {
('Click event');
};
Return (
<div>
<button onClick={() => setCount(count + 1)}>Trigger rendering (current: {count})</button>
{/* Even if Child is wrapped in, it will still be re-rendered */}
<Child onClick={handleClick} />
</div>
);
};
// Subcomponents (using optimization)
const Child = (({ onClick }) => {
('Subcomponent Rendering'); // This log will be triggered every time the parent component is updated
return <button onClick={onClick}>Subcomponent button</button>;
});
// Problem: Every time the parent component is updated (such as count changes), handleClick will be recreated, resulting in different onClick references passed to the child component.
// Result: Even if the child component is wrapped, it will be re-rendered due to the reference changes of the function in props.
Syntax and Parameters
const memoizedFn = useCallback(
() => { /* Function logic */ },
[dep1, dep2] // Dependency array
);
// Parameter 1: Functions that need to be cached.
// Parameter 2: Dependency array (dependencies similar to useEffect).
// Return value: a memorized function reference (reference remains unchanged when dependency remains unchanged).
// ✅ Correct: Dependencies include count, avoid forming closures and resolve
const handleClick = useCallback(() => {
(count);
}, [count]);