Repository navigation
useCallback
By default, React re-creates function definitions on every render. useCallback caches a function definition between renders, returning the exact same function instance as long as its dependencies do not change.
Note: Typically used to pass stable function references to
React.memocomponents or asuseEffectdependencies.
When a function that fetches data or performs side effects is defined inside a component, its reference changes on every render. If you pass that function directly into a useEffect dependency array without useCallback, it will trigger the effect on every render, resulting in an infinite execution loop.
import { useEffect, useCallback } from 'react';
const Component = () => {
// Preserved function reference across re-renders
const fetchData = useCallback(() => {
fetch('/api').then(...);
}, []);
// Prevents infinite re-triggering since fetchData maintains a stable reference
useEffect(() => {
fetchData();
}, [fetchData]);
};When passing callback functions down to child components wrapped in React.memo, regular inline functions break optimization because their reference changes on every parent render, forcing the child to re-render unnecessarily. The useCallback ensures a stable reference, allowing React.memo to properly skip re-renders when props remain unchanged.
import { useCallback, memo } from 'react';
// Child component wrapped in React.memo
const ExpensiveChild = memo(({ onClick }) => {
return <button onClick={onClick}>Click!</button>;
});
const Parent = () => {
// Stable reference across parent renders
const handleClick = useCallback(() => {
console.log('Button clicked');
}, []);
return (
<ExpensiveChild onClick={handleClick} />
);
};- Home
- Functional Components
- Props
- Fragments
- Memoization
- Forward Ref
- Portals
- Suspense
-
Hooks
- State
- Context
- Effect
- Ref
- Performance
- Concurrent
- Form
- Utility
- Custom Hooks