ReactJS useCallback Hook

In React, functions are re-created every time a component re-renders. While this behavior is normal, it can sometimes cause unnecessary re-renders in child components, especially when functions are passed as props. The useCallback Hook helps solve this problem by preserving function references between renders.


What Is useCallback?

useCallback is a React Hook that returns a memoized version of a function. code>useCallback allows you to store and reuse the same function reference between renders instead of creating a new function every time a component re-renders.

In React, a component is a JavaScript function. Each time it re-runs, all functions declared inside it are recreated in memory, even if their logic has not changed. useCallback prevents this unnecessary recreation by memoizing the function itself.

useCallback tells React to remember a function and reuse it until its dependencies change.


Importing useCallback


import { useCallback } from "react";


Basic Syntax Of useCallback

Syntax without Arguments

const memoizedFunction = useCallback(() => {
  // function logic
}, [dependencies]);

What This Means
  • The function is created once
  • React stores the function reference
  • A new function is created only when dependencies change
Syntax with Arguments

useCallback(callback, dependencies)

Arguments:
1. callback
  • The function you want React to remember.
2. dependencies
  • An array of values the function depends on.
  • The function will be recreated only when one of these values changes.

Example 1: Without useCallback

Parent Component

import { useState } from "react";
import Child from "./Child";

function Parent() {
  const [count, setCount] = useState(0);

  // Function is recreated on every render
  const incrementCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <h2>Parent Component</h2>
      <p>Count: {count}</p>

      <Child onIncrement={incrementCount} />
    </div>
  );
}

export default Parent;

Explanation:
  1. Parent component renders
  2. incrementCount function is created
  3. Parent state updates
  4. Parent re-renders
  5. A new incrementCount function is created again
  6. Child receives a new function reference
Child Component

function Child({ onIncrement }) {
  return (
    <div>
      <h3>Child Component</h3>
      <button onClick={onIncrement}>
        Increment from Child
      </button>
    </div>
  );
}

export default Child;


Example 2 : With useCallback

Parent Component

import { useState, useCallback } from "react";
import Child from "./Child";

function Parent() {
  const [count, setCount] = useState(0);

  // Function is memoized using useCallback
  const incrementCount = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []);

  return (
    <div>
      <h2>Parent Component</h2>
      <p>Count: {count}</p>

      <Child onIncrement={incrementCount} />
    </div>
  );
}

export default Parent;

Explanation:
  1. incrementCount is created using useCallback
  2. React stores the function reference
  3. The same function is passed to the child on every render
  4. Parent state updates when the function is called
Child Component

function Child({ onIncrement }) {
  return (
    <div>
      <h3>Child Component</h3>
      <button onClick={onIncrement}>
        Increment from Child
      </button>
    </div>
  );
}

export default Child;


Real-World Scenarios Where useCallback Is Useful

  1. Passing click handlers from a parent component to child components
    When a parent re-renders, the click handler functions are recreated. useCallback keeps these handlers stable and avoids unnecessary updates.

  2. Dashboard pages with multiple widgets receiving action functions
    Widgets often receive callback functions from a container component. useCallback helps prevent widget re-renders caused by changing function references.

  3. Form components passing submit or change handlers to input fields
    When typing in forms, frequent re-renders occur. useCallback prevents input components from re-rendering due to recreated handlers.

  4. Rendering large lists where each item receives the same callback
    Passing a newly created function to each list item can impact performance. useCallback ensures a single stable function reference is reused.

  5. Child components sending data back to the parent using callbacks
    Even in child-to-parent communication, the callback is defined in the parent. useCallback keeps that function reference consistent across renders.

  6. Parent components that re-render frequently due to state changes
    Frequent parent updates can cause unnecessary function recreation. useCallback prevents child components from being affected by these updates.

  7. Using the same event handler across multiple UI elements
    Reusing a memoized callback avoids creating multiple function instances for the same logic.

  8. Functions used inside other hooks like useEffect or useMemo
    Changing function references can trigger unwanted re-execution. useCallback keeps dependencies stable.

  9. Complex pages with deeply nested component structures
    In large applications, unnecessary re-renders become noticeable. useCallback helps reduce wasted rendering work.

  10. Reusable component libraries where prop stability matters
    Stable callback references make reusable components more predictable and efficient.

Final Summary

The useCallback Hook helps optimize React applications by preventing unnecessary function recreation during re-renders. It is especially useful when functions depend on state or props and are reused across renders. By memoizing callback functions and recreating them only when their dependencies change, useCallback improves performance without altering application behavior.

Rule to Remember If you want React to remember a function, use useCallback. If you want React to remember a value, use useMemo.