Categories
React

Using the useCallback and useMemo Hooks in React Components

Spread the love

The useCallback and useMemo hooks are 2 more advanced hooks that are added in addition to the basic useState and useEffect hooks.

They’re both useful in different ways.

In this article, we’ll look at how to use the useCallback and useMemo hooks in our React components.

useCallback

The useCallback hook is used for memoizing callbacks that we may call multiple times.

Using the useCallback hook, we can cache callbacks that are in a component so that they won’t be created more than once unless a state or prop changes.

For instance, instead of writing:

import React from "react";

export default function App() {
  const handleClick = () => {
    console.log("Clicked");
  };
  return <button onClick={handleClick}>Click Me</button>;
}

We can write:

import React, { useCallback } from "react";

export default function App() {
  const handleClick = useCallback(() => console.log("Clicked"), []);

  return <button onClick={handleClick}>Click Me</button>;
}

We pass in our callback to the useCallback hook so that the function we passed in the first argument is called when we click on the button.

But the handleClick function is only created once instead of every render.

The 2nd argument is an array where we can pass in the items that we can watch in the function.

For instance, if we write:

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

export default function App() {
  const [num, setNum] = useState(0);

  const increment = useCallback(() => setNum((c) => c + 1), []);
  const handleClick = useCallback(() => console.log(num), []);

  return (
    <>
      <button onClick={increment}>Increment</button>
      <button onClick={handleClick}>Click Me</button>
    </>
  );
}

The handleClick function will always log 0 since the function is only created when the component is mounted as we have an empty array in the 2nd argument.

However, if we pass in [num] to useCallback :

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

export default function App() {
  const [num, setNum] = useState(0);

  const increment = useCallback(() => setNum((c) => c + 1), []);
  const handleClick = useCallback(() => console.log(num), [num]);

  return (
    <>
      <button onClick={increment}>Increment</button>
      <button onClick={handleClick}>Click Me</button>
    </>
  );
}

then the console log shows the latest value of num when we click on Click Me.

This is because the handleClick function is re-created when num changes since we passed in [num] in the 2nd argument of useCallback .

useMemo

The useMemo hook lets us compute a value that’s derived from existing states when any of the states that it depends on changes.

For instance, we can write:

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

export default function App() {
  const [num1, setNum1] = useState(0);
  const [num2, setNum2] = useState(0);

  const increment1 = useCallback(() => setNum1((c) => c + 1), []);
  const increment2 = useCallback(() => setNum2((c) => c + 1), []);
  const sum = useMemo(() => num1 + num2, [num1, num2]);

  return (
    <>
      <button onClick={increment1}>increment 1</button>
      <button onClick={increment2}>increment 2</button>
      <p>num1: {num1}</p>
      <p>num2: {num2}</p>
      <p>sum: {sum}</p>
    </>
  );
}

We have the num1 and num2 states which are changed when we click the buttons.

Then we define the sum variable, which is assigned from the useMemo hook.

We pass in a function that returns num1 and num2 added together.

In the 2nd argument of useMemo , we pass in num1 and num2 , which we’re watching.

It means that when num1 or num2 changes, the returned value of useMemo callback will be assigned to sum .

Therefore, when we click on either button, sum changes.

Conclusion

We can use useCallback to cache functions and only recreate them when a state or prop changes.

The useMemo lets create variables derived from state or prop values and cache them until any dependent value changes.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *