The React useCallback hook can help you improve performance of your React apps. It is weird that useCallback hook is one of the hooks that are not discussed as often. In this tutorial, you will learn about what React useCallback is, how it works and how to use it. You will also learn a bit about memoization.
The main purpose of React useCallback hook is to memoize functions. The main reason for this is increasing performance of your React applications. How is this related? Every time your component re-renders it also re-creates functions that are defined inside it. Memoizing functions helps you prevent this.
When you memoize a function with useCallback hook that function is basically stored in cache. Quick example. Imagine that something causes your component to re-render. Let’s say there is a change of state. Usually, this re-render would, by default, also cause React to re-create all functions defined in your component.
This may not happen with useCallback hook and memoization. When you memoize a function React may not re-create that function just because the component re-rendered. Instead, React can skip the re-creation and return the memoized function. This can help you save resources and time and improve performance of your application.
If you already know the React useEffect hook you will find the syntax of useCallback familiar. They are actually almost the same. Similarly to useEffect hook, useCallback also accepts two parameters. The first parameter is the function you want to memoize. The second parameter is an array of dependencies.
This array of dependencies specifies values React should watch. When any of these values changes, React should re-create the function. Otherwise, it should return the memoized version of the function.
The array of dependencies is important. It helps React understand when to return the memoized function and when to re-create it. Why re-create it? Wasn’t the purpose of memoization preventing this from happening? Well, yes and no. Yes, you want to prevent the function from being re-created.
However, if the function depends on some input, you want to re-create that function when the input changes. Otherwise, you would execute the function with old input that is no longer relevant. For example, let’s say you have a function that greets the user using their name.
This function will depend on the name of the current user. If you memoize it the first time you create it, it will remember the first name. When the name changes, it will not register it. It will greet every subsequent user using the first name. Solution for this is adding the name as a dependency.
When you specify the name as dependency, React will automatically re-create the function when the name changes. When new user arrives, and the name changes, the function will be re-created. It will update its input, use the latest value of name, and greet the user using a correct name.
Let’s demonstrate the power of dependencies and memoization on a simple example. Imagine you have a simple component that contains input and button. The input allows the user to specify her name. This name will be stored in local state created with useState hook. Click on the button logs the name to the console.
The handler function for the button will be memoized with useCallback hook. On the first try, you forget to include the name as a dependency for the hook. What you do instead is specify the dependency array as an empty array. This tells React that it should create the function only on the initial render.
When something happens that causes a subsequent re-render of the component, it should return the memoized version of the function. Remember that changing state causes React to re-render. This helps keep everything in sync. What happens when the user write her name in the input and clicks the button?
The user will be probably surprised. The console will show the initial value of the “name” state. The reason is that when the function was created, the value of name was the initial value. When the name changed React didn’t re-create the function and the function didn’t know the name has changed.