DEV Community

Marcelle Vargas
Marcelle Vargas

Posted on • Originally published at marcelle-vargas.Medium on

Discovering React’s useCallback

There are several React hooks, and recently, while studying, I found that this hook deserves more of my attention.

But before diving into what useCallback actually is, let’s start with a preliminary question: What exactly is a hook?

What is a hook?

Informally, hooks can be thought of as the “components” of business logic. When you need to execute the same logic in multiple places, you can isolate that logic in a hook and call it from any part of your system. This concept also applies to React’s native hooks.

Now that we understand that hooks are encapsulated logics meant for reuse, we can move on to the second topic necessary to understand useCallback: React’s rendering process.

How does React.js render components?

React introduced the component-based architecture pattern in a very efficient way, where each part of your interface can be isolated and reused within the system. This significantly improved the organization and maintenance of web systems. To render these components, they need to be called within a parent component that functions as your page.

So far, this setup isn’t problematic, but it still doesn’t solve the performance issue, as every state change requires updating the entire page. There are other approaches to address this issue, depending on the context, but today we’ll focus on useCallback.

So, what does useCallback do?

Basically, it’s a hook that caches your function, preventing it from being recreated unnecessarily. It will only be executed again if one of its dependencies changes (similar to useEffect).

Example with code

Let’s create a counter where the user can click a button to increment a value and also increase the interval step.

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

const ChildComponent = React.memo(({ onIncrement }) => {
  console.log("ChildComponent rendered");
  return (
    <div>
      <button onClick={onIncrement}>Increment in Child</button>
    </div>
  );
});

function ParentComponent() {
  const [count, setCount] = useState(0);
  const [otherState, setOtherState] = useState(false);
  const [incrementStep, setIncrementStep] = useState(1);

  const incrementWithoutCallback = () => {
    setCount((prevCount) => prevCount + incrementStep);
  };

  console.log("ParentComponent rendered");

  return (
    <div>
      <h1>Counter: {count}</h1>

      <h2>Without useCallback</h2>
      <ChildComponent onIncrement={incrementWithoutCallback} />

      <button onClick={() => setOtherState(!otherState)}>
        Toggle Other State
      </button>

      <button onClick={() => setIncrementStep((prev) => prev + 1)}>
        Increase Increment Step
      </button>
    </div>
  );
}

export default ParentComponent;
Enter fullscreen mode Exit fullscreen mode

In the example above, the child component is rendered each time there is a change in the parent component.


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

const ChildComponent = React.memo(({ onIncrement }) => {
  console.log("ChildComponent rendered");
  return (
    <div>
      <button onClick={onIncrement}>Increment in Child</button>
    </div>
  );
});

function ParentComponent() {
  const [count, setCount] = useState(0);
  const [otherState, setOtherState] = useState(false);
  const [incrementStep, setIncrementStep] = useState(1);

  const incrementWithCallback = useCallback(() => {
    setCount((prevCount) => prevCount + incrementStep);
  }, [incrementStep]);

  console.log("ParentComponent rendered");

  return (
    <div>
      <h1>Counter: {count}</h1>

      <h2>With useCallback</h2>
      <ChildComponent onIncrement={incrementWithCallback} />

      <button onClick={() => setOtherState(!otherState)}>
        Toggle Other State
      </button>

      <button onClick={() => setIncrementStep((prev) => prev + 1)}>
        Increase Increment Step
      </button>
    </div>
  );
}

export default ParentComponent;
Enter fullscreen mode Exit fullscreen mode

When we use useCallback, the child component will only re-render when the dependency changes.

I hope this text has helped you better understand how useCallback works.

Hi, my name is Marcelle, and I’m a web developer. :)

I’ve been working in tech since 2016, and I’m passionate about what I do. That’s why I’m always studying and sharing my study notes in the form of articles.

marcellevargas - Overview

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay