useCallback
Master useCallback — the hook for stabilising function references between renders. Learn when it genuinely helps performance and when it is unnecessary overhead.
Last reviewed: January 2025
🔍 What Is It?
useCallback(fn, deps) returns a memoised version of fn. The function is only recreated when a dependency in deps changes.
const handleSubmit = useCallback(async (data: FormData) => {
await submitForm(data);
onSuccess();
}, [onSuccess]); // only recreated when onSuccess changesuseCallback is equivalent to useMemo(() => fn, deps). It is just a more readable shorthand for memoising functions specifically.
When it matters:
- →Passing a callback to a
React.memowrapped child - →Passing a function as a
useEffectdependency - →Passing a callback to a custom hook that uses it as a dependency
🎯 Why Do We Need It?
In JavaScript, every function definition creates a new reference:
const fn1 = () => {};
const fn2 = () => {};
console.log(fn1 === fn2); // false — different referencesEvery time a parent component re-renders, every inline function is recreated as a new reference. If you pass that function to a child wrapped in React.memo, the child re-renders anyway — because the prop reference changed, even though the function does the same thing.
useCallback stabilises the reference so memoised children can actually skip re-renders.
🏗️ What Happens in Real Projects?
In a large data table component:
- →Memoised row components receive onRowClick, onRowExpand, onRowDelete callbacks
- →Without useCallback: all rows re-render whenever the parent re-renders (even for unrelated state changes)
- →With useCallback: row re-renders only when the specific callback logic changes
In a search component:
- →A debounced search function passed to a memoised input component
- →The function should not change on every render or the debounce resets
⚙️ How It Works
React stores the function reference in its hook memory. On each render, it compares the dependencies using Object.is(). If all dependencies are unchanged, it returns the same function reference from the previous render. If any dependency changed, it stores the new function.
Important: The function body still has access to the latest values via closure. The memoised reference just prevents unnecessary re-renders downstream.
💻 Example
useCallback in Production — Stable callbacks for memoised children and effect dependencies.
🤔 Common Confusions
❓ Should I wrap every function in useCallback?
No. useCallback has overhead — the comparison and cache. If the child is not memoised with React.memo, useCallback provides zero benefit. Only use it when: (1) passing to a React.memo child, (2) using as a useEffect dependency, (3) passing to a custom hook that uses it as a dependency.
❓ What is the difference between useCallback and useMemo?
useCallback memoises a function reference. useMemo memoises a computed value. useCallback(fn, deps) is exactly equivalent to useMemo(() => fn, deps). They are the same mechanism — useCallback is just a more readable shorthand for the function case.
❓ Does useCallback make the function faster?
No. useCallback does not make the function run faster. It only stabilises the reference to prevent unnecessary re-renders of children. The function itself executes at the same speed.
🚨 Common Production Issues
**Over-optimisation** — Wrapping every function in useCallback adds boilerplate and comparison overhead with no benefit if the children are not memoised. Profile first.
**Stale closure** — If a dependency is missing from the array, the callback captures a stale value. Always follow exhaustive-deps.
**Infinite loop with useEffect** — A function created inside a component (without useCallback) used as a useEffect dependency causes the effect to re-run every render. Fix: useCallback or move the function outside the component.
✅ Best Practices
Only use useCallback when passing to React.memo children or as useEffect dependencies
Follow exhaustive-deps — include all values from the component scope used inside the function
Stable setter functions from useState (setX) do not need to be in dependencies — React guarantees they are stable
If a callback has no dependencies, the empty array [] means it is created once
Combine with React.memo for the complete performance optimisation pattern
🏛️ Architect's Note
useCallback is one of the most over-used hooks in React codebases. Developers see it as a best practice and wrap every function, creating a forest of useCallback calls that add complexity without measurable benefit. The real pattern: build the feature first without optimisation, profile with React DevTools Profiler, then apply React.memo + useCallback only to the components that are actually slow. In most apps, only a handful of components need this treatment.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
↗ Where this topic fits
React Technology Guide
Return to the React learning hub.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Python Developer Career Path
A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.
Sources
Sources / References
Use these React references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide React learning path
Browse the full React topic collection and learning order on SplashRide.
React Interview Prep
Practice React interview questions and scenario-based answers.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Python Developer Career Path
A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.
useMemo
Understand useMemo — React's hook for memoising expensive computed values. Learn when it actually helps performance, when it hurts, and the patterns senior engineers use in real applications.
React.memo
Master React.memo — the higher-order component for preventing unnecessary re-renders. Learn when it helps, when it hurts, and how to use it correctly with useCallback and useMemo.