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 usesuseEffect
and depends on the callback prop, an unstable function reference will causeuseEffect
to 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
count
changes, theChild
component'suseEffect
re-runs because thecallback
function is recreated every time theParent
renders.
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
callback
reference remains stable, so theChild
component'suseEffect
won'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
useEffect
that 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)