The useCallback Hook and Stabilizing Callback Props0%

The useCallback Hook and Stabilizing Callback Props

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

The useCallback Hook and Stabilizing Callback Props

1. The Problem of Re-created Functions

In JavaScript, functions are first-class objects. Every time a component executes its render cycle, any function declared inside that component's body is re-instantiated as a brand new object in memory:

JavaScript
// On Render 1:
const fn1 = () => console.log('clicked');
 
// On Render 2:
const fn2 = () => console.log('clicked');
 
console.log(fn1 === fn2); // FALSE! Distinct memory addresses!

If you pass this function down as a prop to a child component wrapped in React.memo, the child will re-render on every parent render, because React sees a different function reference every time!

2. What is useCallback?

useCallback is a React hook that caches a function definition between renders. It returns the exact same function reference across renders unless one of its dependencies changes.

Output
useCallback(fn, dependencies)
├─ Dependencies unchanged? ──► Returns cached function reference from previous render!
└─ Dependencies changed? ──► Re-creates function and caches new reference!

3. Practical Example: Stabilizing Callbacks for Memoized Children

Consider a parent with an expensive list of items:

JSX
import React, { useState, useCallback, memo } from 'react';
 
// 1. Expensive child component wrapped in React.memo
const StudentRow = memo(function StudentRow({ student, onRemove }) {
console.log(`Rendering row: ${student.name}`);
return (
<li className="student-row">
<span>{student.name}</span>
<button onClick={() => onRemove(student.id)}>Remove</button>
</li>
);
});
 
export default function StudentRoster() {
const [students, setStudents] = useState([
{ id: 1, name: 'Rahul' },
{ id: 2, name: 'Priya' },
{ id: 3, name: 'Aman' }
]);
const [theme, setTheme] = useState('light');
 
// ❌ Without useCallback: handleRemove would get a new reference every time 'theme' toggles!
// ✅ With useCallback: reference is STABLE across all renders!
const handleRemove = useCallback((id) => {
setStudents((prev) => prev.filter((s) => s.id !== id));
}, []); // Empty deps because functional update 'setStudents(prev => ...)' needs no external state!
 
return (
<div className={`roster theme-${theme}`}>
<button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
 
<ul>
{students.map((student) => (
<StudentRow
key={student.id}
student={student}
onRemove={handleRemove} // Stable reference passed!
/>
))}
</ul>
</div>
);
}

Now, when you click "Toggle Theme":

  1. 1
    StudentRoster re-renders to update the theme.
  2. 2
    handleRemove retains its exact same cached reference.
  3. 3
    StudentRow checks its props: student is identical, and onRemove is identical.
  4. 4
    All <StudentRow> components skip re-rendering entirely!

4. The Golden Pair: useCallback + React.memo

Remember: useCallback does not make function creation faster.

In fact, calling useCallback has a slight overhead (allocating arrays and comparing dependencies).

useCallback is only useful when:

  1. 1
    Passing callbacks to memoized child components (React.memo).
  2. 2
    Passing callbacks as dependencies to other hooks (e.g. inside a useEffect dependency array).

Interactive Quiz

Practice Quiz

Question 1
What is the primary purpose of the useCallback hook in React?
Question 2
Why does useCallback have little benefit if the child component receiving the function is NOT wrapped in React.memo?
Question 3
How does combining useCallback with functional state updates (setCount(prev => prev + 1)) help dependency arrays?
Question 4
When is useCallback necessary inside a useEffect workflow?
Question 5
What does useCallback(fn, deps) return?
Next Lesson

The useMemo Hook and Expensive Computations

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext