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.

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay