useCallback is a React Hook that helps you optimize your component by memoizing callback functions. It ensures that the function reference stays the same across renders unless its dependencies change. This is particularly useful when you pass a function as a prop to child components, as it prevents unnecessary re-renders or re-executions of child components' useEffect hooks.
Why Use useCallback?
Prevent Unnecessary Re-Renders:
If you pass a callback function as a prop to a child component, that function gets recreated on every render. This can cause child components to re-render unnecessarily.Stable Function References:
If a child component usesuseEffectand depends on the callback prop, an unstable function reference will causeuseEffectto re-run unnecessarily.Optimize Performance:
Helps prevent expensive computations or operations caused by frequent re-creation of the same function.
Syntax
const memoizedCallback = useCallback(
() => {
// Your logic here
},
[dependencies] // Array of dependencies
);
- Callback Function: The function you want to memoize.
- Dependencies: The values that the function depends on. If these change, the function will be recreated.
Example Without useCallback
import React, { useState, useEffect } from "react";
const Child = ({ callback }) => {
useEffect(() => {
callback(); // Runs whenever the `callback` reference changes
}, [callback]);
return <div>Child Component</div>;
};
const Parent = () => {
const [count, setCount] = useState(0);
const callback = () => {
console.log("Callback called");
};
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<Child callback={callback} />
</div>
);
};
export default Parent;
-
Problem: Even if the
countchanges, theChildcomponent'suseEffectre-runs because thecallbackfunction is recreated every time theParentrenders.
Fixing with useCallback
import React, { useState, useEffect, useCallback } from "react";
const Child = ({ callback }) => {
useEffect(() => {
callback(); // Runs only when `callback` changes
}, [callback]);
return <div>Child Component</div>;
};
const Parent = () => {
const [count, setCount] = useState(0);
const callback = useCallback(() => {
console.log("Callback called");
}, []); // Dependencies are empty, so the callback is memoized
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<Child callback={callback} />
</div>
);
};
export default Parent;
-
Solution: Now, the
callbackreference remains stable, so theChildcomponent'suseEffectwon't re-run unnecessarily.
When to Use useCallback?
- When you pass functions as props to child components.
- When the child component uses
React.memo()for optimization. - When the child component depends on
useEffectthat uses the function.
Common Misuse
Do not use useCallback for every function. It's only beneficial if:
- The function is passed as a prop to a child.
- The function is computationally expensive to recreate.
Top comments (0)