Skip to main content

When to use useCallback()?

When to use useCallback()

The useCallback() hook is needed not to speed up a function, but to keep the same reference to a function across renders.

This matters when:

  1. The function is passed to a child component, especially if it is wrapped in React.memo.
  2. The function is used in useEffect / useMemo and must stay stable (so it does not trigger the effect again).
  3. You want to avoid unnecessary recreation of functions on every render (which causes unnecessary re-renders).

Example 1: passing a function to a React.memo component

javascript
const Button = React.memo(({ onClick }) => { console.log("Button re-render"); return <button onClick={onClick}>+</button>; }); function Counter() { const [count, setCount] = useState(0); // Without useCallback → a new function is created on every render const increment = useCallback(() => setCount(c => c + 1), []); return ( <div> <p>{count}</p> <Button onClick={increment} /> </div> ); }

Here:

  • increment is created once, since the dependencies are [].
  • The button does not re-render without a reason. Without useCallback, Button would re-render on every change of count.

Example 2: a stable dependency in useEffect

javascript
function FetchUser({ id }) { const fetchUser = useCallback(() => { return fetch(`/api/user/${id}`).then(res => res.json()); }, [id]); useEffect(() => { fetchUser(); }, [fetchUser]); // useEffect fires only when id changes }

Without useCallback, fetchUser would be recreated every render, and useEffect would fire every time - even if id had not changed.


Summary - when it is actually worth using

SituationWorth using?Why
Passing a function to a React.memo componentYesAvoids unnecessary re-renders
Using a function in useEffect / useMemoYesStabilizes the dependency
Calling the function directly inside JSXNoPointless, it is not preserved
The function does not depend on props or stateOK with []Created only once
A lightweight function that does not affect othersNoThe optimization is not worth it

What happens if you do not specify dependencies

javascript
const memoizedFn = useCallback(() => { doSomething(a, b); });

Without a dependency array:

  • useCallback will recreate the function on every render - meaning no memoization happens at all.

  • This is equivalent to simply writing:

    javascript
    const memoizedFn = () => doSomething(a, b);

For useCallback to work, you need to pass dependencies that tell React when the function should actually be updated.


Example with dependencies

javascript
const handleClick = useCallback(() => { console.log(count); }, [count]);
  • The function is recreated only if count changed.
  • If you had not specified [count], the function would always contain a "frozen" count from the first render.

Important to remember

RuleExplanation
useCallback(fn, deps) caches the function referenceThe function is created anew only when the dependencies change
If you skip the dependenciesThe function is recreated on every render (memoization does not work)
If you set []The function is created once at mount and never updated
Specify every value used insideOtherwise the closure will hold stale data

Summary

QuestionAnswer
When to use useCallback()When you need a function to keep its reference across renders (React.memo, useEffect, useMemo)
What happens without dependenciesThe function is recreated every render - memoization does not work
What happens with []The function is created once and never updated
What it returnsThe same function, but with a memoized reference

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.