What does useCallback() do?
What does useCallback() do
useCallback() is a hook that memoizes the function itself,
that is, it keeps its reference between renders,
so that React doesn't create a new function every time
if its dependencies haven't changed.
Syntax
javascript
const memoizedCallback = useCallback(() => {
// function code
}, [dependencies]);- The first argument is the function to "remember".
- The second argument is the dependency array. As long as the dependencies don't change, React will return the same function.
Example without useCallback (not optimized)
javascript
function App() {
const [count, setCount] = useState(0);
// A new function is created on every render
const handleClick = () => {
setCount(count + 1);
};
return <Button onClick={handleClick} />;
}If Button is wrapped in React.memo,
it will still re-render,
because handleClick is a new reference every time.
Example with useCallback (optimized)
javascript
import { useState, useCallback } from "react";
function App() {
const [count, setCount] = useState(0);
// The function is recreated only when count changes
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Button onClick={handleClick} />;
}
const Button = React.memo(({ onClick }) => {
console.log("Button re-render");
return <button onClick={onClick}>+</button>;
});Now handleClick doesn't change its reference on every render,
and React.memo(Button) doesn't re-render without a reason.
What useCallback() returns
useCallback() returns the same function
you passed it, but memoized (with a preserved reference).
Put simply:
javascript
useCallback(fn, deps)is equivalent to:
javascript
useMemo(() => fn, deps)When useCallback() is useful
| Situation | Why use it |
|---|---|
| You pass functions to child components | To avoid causing them an unnecessary re-render |
You use useEffect or useMemo and want a stable dependency | So the effect doesn't fire every time |
| In components where a handler is created inside JSX | To avoid recreating the function on every render |
Example: stabilizing a dependency in useEffect
javascript
function Example({ userId }) {
const fetchUser = useCallback(() => {
return fetch(`/api/user/${userId}`).then(r => r.json());
}, [userId]);
useEffect(() => {
fetchUser().then(console.log);
}, [fetchUser]); // doesn't trigger an infinite loop
}Without useCallback, fetchUser would be created every time,
and useEffect would fire infinitely.
Important to remember
| Rule | Explanation |
|---|---|
useCallback doesn't speed up the code itself | It only prevents unnecessary re-renders |
| Don't use it everywhere | Only if the function is passed as a prop or used in dependencies |
| Works by reference | React compares not the content of the function but its reference in memory |
Summary
| Question | Answer |
|---|---|
What does useCallback() do | Memoizes (caches) a function so it isn't recreated on every render |
| When is it recreated | Only if the dependencies change |
| What it returns | A stable (the same) reference to the function |
| When to use it | When the function is passed to a child component or used in useEffect |
| When not needed | If the function doesn't affect re-renders or isn't used as a dependency |
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.