useCallback Hook

🪝 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

useCallback is a performance optimization Hook. It should be used only when memoizing a function provides a measurable performance benefit.

🎯 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]);
PartDescription
useCallback()Memoizes a function.
Callback FunctionThe function whose reference should be preserved.
Dependency ArrayDetermines when the function should be recreated.

🔄 How useCallback Works

Component Renders
React Checks Dependencies
Dependencies Changed?
Component Continues Rendering
Yes → Create a New Function
No → Return the Cached Function

💻 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 useCallbackWith 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

📊 useMemo vs useCallback

FeatureuseMemouseCallback
ReturnsA memoized value.A memoized function.
Primary PurposeCache expensive calculations.Cache callback functions.
Typical UsageDerived 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

useCallback memoizes the function reference, not the function's result. If you need to cache a calculated value, use useMemo instead.

✅ 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.

Summary

The useCallback Hook memoizes function references, helping React avoid unnecessary function recreation between renders. It is particularly useful when passing callbacks to memoized child components or using functions in dependency arrays. Used appropriately, useCallback can improve application performance while keeping React components efficient and maintainable.