DEV Community

Muhammad Atif Iqbal
Muhammad Atif Iqbal

Posted on

What is 'useCallback' in React?

useCallback is a React Hook that helps you optimize your component by memoizing callback functions. It ensures that the function reference stays the same across renders unless its dependencies change. This is particularly useful when you pass a function as a prop to child components, as it prevents unnecessary re-renders or re-executions of child components' useEffect hooks.


Why Use useCallback?

  1. Prevent Unnecessary Re-Renders:
    If you pass a callback function as a prop to a child component, that function gets recreated on every render. This can cause child components to re-render unnecessarily.

  2. Stable Function References:
    If a child component uses useEffect and depends on the callback prop, an unstable function reference will cause useEffect to re-run unnecessarily.

  3. Optimize Performance:
    Helps prevent expensive computations or operations caused by frequent re-creation of the same function.


Syntax

const memoizedCallback = useCallback(
  () => {
    // Your logic here
  },
  [dependencies] // Array of dependencies
);
Enter fullscreen mode Exit fullscreen mode
  • Callback Function: The function you want to memoize.
  • Dependencies: The values that the function depends on. If these change, the function will be recreated.

Example Without useCallback

import React, { useState, useEffect } from "react";

const Child = ({ callback }) => {
  useEffect(() => {
    callback(); // Runs whenever the `callback` reference changes
  }, [callback]);

  return <div>Child Component</div>;
};

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

  const callback = () => {
    console.log("Callback called");
  };

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child callback={callback} />
    </div>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode
  • Problem: Even if the count changes, the Child component's useEffect re-runs because the callback function is recreated every time the Parent renders.

Fixing with useCallback

import React, { useState, useEffect, useCallback } from "react";

const Child = ({ callback }) => {
  useEffect(() => {
    callback(); // Runs only when `callback` changes
  }, [callback]);

  return <div>Child Component</div>;
};

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

  const callback = useCallback(() => {
    console.log("Callback called");
  }, []); // Dependencies are empty, so the callback is memoized

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child callback={callback} />
    </div>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode
  • Solution: Now, the callback reference remains stable, so the Child component's useEffect won't re-run unnecessarily.

When to Use useCallback?

  • When you pass functions as props to child components.
  • When the child component uses React.memo() for optimization.
  • When the child component depends on useEffect that uses the function.

Common Misuse

Do not use useCallback for every function. It's only beneficial if:

  1. The function is passed as a prop to a child.
  2. The function is computationally expensive to recreate.

Top comments (0)