React useCallback Interview Guide
What is useCallback?
Section titled “What is useCallback?”useCallback is a React Hook that memoizes a function and returns the same function instance between renders unless its dependencies change.
const memoizedFn = useCallback(() => { console.log("Hello");}, []);Why?
To prevent unnecessary recreation of functions and avoid unwanted child component re-renders.
What Problem Does useCallback Solve?
Section titled “What Problem Does useCallback Solve?”Normally, functions are recreated on every render.
const handleClick = () => { console.log("Clicked");};Every render creates a new function reference.
useCallback preserves the same function reference.
const handleClick = useCallback(() => { console.log("Clicked");}, []);Useful when passing functions to memoized child components.
How useCallback Works
Section titled “How useCallback Works”flowchart TD
A[Component Renders] --> B{Dependencies Changed?}
B -->|No| C[Return Existing Function Reference]
B -->|Yes| D[Create New Function]
D --> E[Store New Function & Dependencies]
C --> F[Pass Stable Reference]
E --> F
Internally React stores:
{ callback: functionRef, dependencies: [...]}On every render React compares the dependency array.
- Same dependencies -> returns the previous function.
- Changed dependencies -> creates and stores a new function.
useCallback vs useMemo
Section titled “useCallback vs useMemo”| useCallback | useMemo |
|---|---|
| Memoizes a function | Memoizes a value |
| Returns a function | Returns computed value |
| Used for callbacks/event handlers | Used for expensive computations |
const calculate = useMemo(() => a + b, [a, b]);
const handleClick = useCallback(() => { console.log(a);}, [a]);When Should You Use useCallback?
Section titled “When Should You Use useCallback?”Use it when:
- Passing callbacks to components wrapped with
React.memo - A callback appears in another Hook’s dependency array
- Avoiding unnecessary child re-renders
Avoid using it everywhere.
Dependency Changes
Section titled “Dependency Changes”const handleClick = useCallback(() => { console.log(count);}, [count]);Whenever count changes, React creates a new callback.
Can useCallback Improve Performance?
Section titled “Can useCallback Improve Performance?”Yes, but only in appropriate scenarios.
const Child = React.memo(({ onClick }) => { console.log("Child Rendered"); return <button onClick={onClick}>Click</button>;});
const handleClick = useCallback(() => { console.log("Clicked");}, []);Without useCallback, a new function reference is passed every render, causing React.memo to re-render the child.
Can It Hurt Performance?
Section titled “Can It Hurt Performance?”Yes.
React must:
- Store callback
- Store dependencies
- Compare dependencies
For simple components, this overhead may outweigh any benefit.
Stale Closure Problem
Section titled “Stale Closure Problem”Incorrect:
const [count, setCount] = useState(0);
const showCount = useCallback(() => { console.log(count);}, []);Output always:
0Correct:
const showCount = useCallback(() => { console.log(count);}, [count]);useCallback with React.memo
Section titled “useCallback with React.memo”Without useCallback:
<Child onClick={() => console.log("Click")} />Each render creates a new function.
oldFn !== newFnReact.memo detects changed props and re-renders.
With useCallback:
const handleClick = useCallback(() => { console.log("Click");}, []);
<Child onClick={handleClick} />Function reference remains stable.
Function Reference Equality
Section titled “Function Reference Equality”const fn1 = () => {};const fn2 = () => {};
console.log(fn1 === fn2); // falseDifferent functions occupy different memory references.
With useCallback:
const fn = useCallback(() => {}, []);The same reference is reused until dependencies change.
Does useCallback Prevent Component Re-renders?
Section titled “Does useCallback Prevent Component Re-renders?”No.
It only memoizes the function.
Components still re-render when:
- State changes
- Props change
- Context changes
useCallback with useEffect
Section titled “useCallback with useEffect”Incorrect:
const fetchData = () => {};
useEffect(() => { fetchData();}, [fetchData]);This causes repeated executions because fetchData changes every render.
Correct:
const fetchData = useCallback(() => { // API call}, []);
useEffect(() => { fetchData();}, [fetchData]);Normal Function vs useCallback
Section titled “Normal Function vs useCallback”Normal:
const handleClick = () => {};Memoized:
const handleClick = useCallback(() => {}, []);When Not to Use useCallback
Section titled “When Not to Use useCallback”- Small components
- Functions not passed as props
- No measurable performance issue
- Premature optimization
Senior-Level Interview Topics
Section titled “Senior-Level Interview Topics”Real-World Performance Example
Section titled “Real-World Performance Example”An e-commerce application contains:
- Product list
- Filters
- Sorting
- Search
Each product card is wrapped in React.memo.
Without useCallback, filter and sort handlers are recreated on every keystroke, causing every product card to re-render.
Using useCallback stabilizes handler references, reducing unnecessary renders.
Why Doesn’t It Always Improve Performance?
Section titled “Why Doesn’t It Always Improve Performance?”Because React must:
- Store callbacks
- Store dependency arrays
- Compare dependencies
If callback creation is cheaper than memoization, performance may decrease.
Relationship with Reconciliation
Section titled “Relationship with Reconciliation”React compares callback props by reference.
prevProps.onClick === nextProps.onClickIf equal:
React.memoskips rendering.
Otherwise:
- Child re-renders.
Debugging Callback Re-renders
Section titled “Debugging Callback Re-renders”Useful tools:
- React DevTools Profiler
- Why Did You Render
- Console logging
console.log("Child rendered");Closures and useCallback
Section titled “Closures and useCallback”useCallback memoizes the function reference, not the captured values.
Always specify correct dependencies to avoid stale closures.
Quick Interview Summary
Section titled “Quick Interview Summary”| Question | Answer |
|---|---|
| Purpose | Memoize function |
| Returns | Function |
| Dependency changes | New function created |
| Primary use case | Prevent child re-renders |
| Works well with | React.memo |
| Similar hook | useMemo |
| Prevents component render? | No |
| Can hurt performance? | Yes |
| Common issue | Stale closure |
Common Interview One-Liner
Section titled “Common Interview One-Liner”
useCallbackmemoizes a function reference between renders. It is primarily used withReact.memoor dependency-based hooks to avoid unnecessary function recreation and child component re-renders.
Key Takeaways
Section titled “Key Takeaways”useCallbackmemoizes function references, not computed values.- It is most beneficial when used with
React.memoor Hook dependency arrays. - Incorrect dependency arrays can lead to stale closures.
- Overusing
useCallbackmay reduce performance due to memoization overhead. - Profile performance before introducing memoization optimizations.