🪝 Introduction to useCallback
The useCallback Hook is a React Hook that lets you memoize a function. Instead of creating a new function during every render, React returns the same function reference until one of its dependencies changes. This helps optimize performance, especially when passing callback functions to child components.
Important
🎯 Why Use useCallback?
Whenever a React component re-renders, any functions declared inside it are recreated. In most cases this is perfectly acceptable. However, when those functions are passed to memoized child components or used as dependencies in other Hooks, recreating them unnecessarily can trigger additional renders or effect executions. useCallback helps prevent this by keeping the same function reference until its dependencies change.
- Prevent unnecessary child component re-renders.
- Keep callback references stable.
- Optimize performance in large applications.
- Reduce unnecessary effect executions.
⚙️ Syntax
Basic Syntax
const memoizedCallback = useCallback(() => {
// Function body
}, [dependencies]);| Part | Description |
|---|---|
| useCallback() | Memoizes a function. |
| Callback Function | The function whose reference should be preserved. |
| Dependency Array | Determines when the function should be recreated. |
🔄 How useCallback Works
💻 Example 1: Basic Usage
Using useCallback
import { useCallback } from "react";
function Counter() {
const handleClick = useCallback(() => {
console.log("Button clicked");
}, []);
return (
<button onClick={handleClick}>
Click Me
</button>
);
}Since the dependency array is empty, React creates the callback once and reuses the same function reference during future renders.
💻 Example 2: Callback with Dependencies
Using State Inside a Callback
import { useState, useCallback } from "react";
function Counter() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<button onClick={increment}>
{count}
</button>
);
}Whenever count changes, React creates a new version of the callback because the dependency has changed.
💻 Example 3: Preventing Child Re-renders
Memoized Callback
import { useCallback } from "react";
function Parent() {
const handleSave = useCallback(() => {
console.log("Saving...");
}, []);
return <Child onSave={handleSave} />;
}When the child component is optimized using techniques such as memoization, a stable callback reference can help avoid unnecessary re-renders.
📊 Without vs With useCallback
| Without useCallback | With useCallback |
|---|---|
| A new function is created on every render. | The same function is reused until dependencies change. |
| May trigger unnecessary child renders. | Can reduce unnecessary renders. |
| No cached function reference. | Function reference is memoized. |
📋 Common Use Cases
Pass stable callback references to memoized child components.
Prevent unnecessary executions when a callback is used inside dependency arrays.
Reuse event handler functions instead of recreating them on every render.
Optimize rendering in components with expensive rendering logic.
📅 Callback Lifecycle
React renders the component.
React checks the dependency array.
If dependencies changed, a new callback is created.
If dependencies remain unchanged, React returns the cached callback.
The callback is recreated only when one or more dependencies change.
📊 useMemo vs useCallback
| Feature | useMemo | useCallback |
|---|---|---|
| Returns | A memoized value. | A memoized function. |
| Primary Purpose | Cache expensive calculations. | Cache callback functions. |
| Typical Usage | Derived values, filtering, sorting. | Event handlers, callbacks, child props. |
⚠️ Common Mistakes
- Using useCallback for every function without measuring performance.
- Providing an incomplete dependency array.
- Expecting useCallback to stop component re-renders.
- Using memoization for simple components where it provides little or no benefit.
Warning
✅ Best Practices
- Use useCallback only when it provides a real performance improvement.
- Always include every dependency used inside the callback.
- Combine useCallback with memoized child components when appropriate.
- Prefer readable code over unnecessary optimization.
- Profile your application before introducing callback memoization.
📚 Official Resource
Learn more about useCallback in the official React documentation at React useCallback Documentation.