When You Should Use React.useCallback

When You Should Use React.useCallback

Ferenc Almasi β€’ 2021 June 28 β€’ Read time 5 min read
  • twitter
  • facebook
React

React has many built-in hooks for the purpose of optimizing performance. In this article, we will dive into the use of useCallback, and have a look at what problems it tries to solve, and how we can actually use it. And most importantly, whether we should use it or not.


Why we need useCallback in React

To understand why we want to use useCallback, and whether we should use it, we first need to understand why it was introduced in the first place.

The useCallback hook in React was introduced to memoizing callbacks. But what exactly is memoization, and why do we need it?

Memoization is the process of caching previous results. Instead of doing heavy calculations for previous executions, we can instead return the cached value for the same function call. That way, we get an optimized performance for function calls.

The problem with callbacks in React is that functions are recreated every time a component is re-rendered, even though they have the same logic. For example, let's say we have the following components:

Copied to clipboard! Playground
import React, { useState } from 'react';

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

    const addAvocado = () => {
        setCount(count + 1);
    };

    return (
        <React.Fragment>
            <Addvocado add={addAvocado} />
            <div>{Array(count).fill('πŸ₯‘').join(',')}</div>
        </React.Fragment>
    );
};

const Addvocado = ({ add }) => {
    console.log('component re-rendered');

    return <button onClick={add}>Add avocado</button>;
};
useCallback.js

This React app has a child component called Addvocado with an add prop that increases the count variable by one, using the addAvocado function. Every time we click the button, the button gets re-rendered, even though no state or visual changes are happening for the Addvocado component.

Child component re-renders, everytime the button is clicked.
The button is re-rendered for each click.

This happens because the component gets a new function as the prop every time we click the button. The underlying reason for this is that even though the function has the same signature, a function in JavaScript can only be equal to itself.

Function equality

Let's create two different functions with the same signature, so we can compare them:

Copied to clipboard! Playground
const avocados01 = () => ['πŸ₯‘', 'πŸ₯‘', 'πŸ₯‘'];
const avocados02 = () => ['πŸ₯‘', 'πŸ₯‘', 'πŸ₯‘'];

avocados01 === avocados02 // returns false
avocados01 === avocados01 // returns true

As you can see, comparing functions will only return true, if we compare the function against itself. This happens because functions are first-class objects in JavaScript, and they behave like any other object, meaning whenever we create one, a new instance will be created, so they will never be the same.

Memoizing callbacks get around this. By always returning the same function, we can avoid unnecessary re-renders.


When to use useCallback

Now that we know exactly why we need a useCallback hook in React, let's have a look at when we actually want to use it.

In the code example above, we are displaying an array as a comma-separated string. These kinds of simple functions are definitely not what you want useCallback used for. Most of the time, we can get away without using a useCallback for every callback function we have, and since you introduce extra complexity using it, you have to ask yourself whether there will be a performance gain from using it.

Don't try to prematurely optimize the performance of your application, you should only optimize your calls if measurements are showing that the performance degrades. And first, you always want to tackle the calculation heavy callbacks, for example, a function rendering a large list of elements.

Looking to improve your skills? Check out our interactive course to master React from start to finish.
Master Reactinfo Remove ads

How to use useCallback

So how do you actually use useCallback? Let's stay with our example and try to fix the component to make it only render the button once. To fix this, we need to wrap the inline function into the useCallback hook like so:

Copied to clipboard! Playground
import React, { useState, useCallback } from 'react';

...

const memoizedAddvocado = useCallback(() => {
    setCount((c) => c + 1);
}, [setCount]);

Note that the callback expects a second argument. This is called a dependency array. It tells React what values to keep track of. If any of the values are changed that is listed in the dependency array, React will call the hook.

As a rule of thumb, every value referenced inside the callback should also be part of the dependency array.

Now in itself, this alone won't do much. In fact, it doesn't solve anything. In order to make useCallback work as expected, we also need to wrap the child component into React.memo, to tell React it should only be re-rendered if one of the passed props change. So based on this, we can change the child component to the following:

Copied to clipboard!
- const Addvocado = ({ add }) => {
+ const Addvocado = React.memo(({ add }) => {
    console.log('component re-rendered');

    return <button onClick={add}>Add avocado</button>;
- };
+ });

Summary

And now the child component will only be rendered once, and no more, and React memoizes the callback as we wanted:

Child component only renders once.

Like to see the code in action? Give it a try on Codesandbox

Try the hook on codesandbox
When to use React useCallback hook
If you would like to see more Webtips, follow @flowforfrank

If you are interested in reading more about React hooks, see more examples for custom hooks or just learn about the basics, make sure to check out the article below.

All You Need to Know About React Hooks
  • twitter
  • facebook
React
Did you find this page helpful?
πŸ“š More Webtips
Mentoring

Rocket Launch Your Career

Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies:

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.