Learn How to use React Js useCallback() hook

GAZAL ARORA
Last Updated: May 13, 2022

Introduction

Hooks are a brand-new feature in React 16.8. They make it possible to use state, and other React capabilities without having to create a class. Nowadays, many hooks are used like useState, useEffect, useContext, useCallback, etc. 

The useCallback hook is used when you have a component in which the child is re-rendering again and again without need.

 

How does the useCallback hook work?

The useCallback hook receives a function(inline callback) and an array of dependencies as a parameter, and this will return a memoized version of the callback as output. It will only be changed if one of the dependencies has changed.

Syntax:

 

import React, { useCallback } from 'react';
function MyFunction{
  const memoized_Callback = useCallback(() => {
  // doSomething 
  }, []);
}

 

The purpose of useCallback()

 

Different function objects with the same code are frequently created inside React components. For example, the handle Button is a new function object in the code below each time MyFunction is rendered.

 

function MyFunction() {
 // handleButton is re-created on each render
 const handleButton = () => {
  console.log('Pressed');
};
 // ...
}

 

As the inline functions are not expensive, a few inline functions per component are acceptable.

 

But sometimes, there is a need to maintain a single function instance between renderings to optimize the performance by saving time and memory. We should use the useCallback() hook in the following cases:

 

  1. A function object prop is accepted by a functional component wrapped in React.memo().
  2. When the function object is a dependency on the other hooks.
  3. When the function is debounced or throttled, i.e., the function has some internal state.

 

import { useCallback } from 'react';
function MyFunction() {
 // handleButton is the same function object
 const handleButton = useCallback(() => {
  console.log('Pressed');
}, []);
 // ...
}

 

Here, given the same dependency values, the useCallback hook returns the same function instance between renderings.

 

 

 

Let us understand through an example. Here, the filename is counterApp.js.

 

import React, { useState, useCallback } from 'react'

const functionCounter = new Set()

const counterApp = () => {
  const [count, setCount] = useState(0)
  const [newCounter, setNewCounter] = useState(0)

  const increment = () => {
    setCount(count + 1)
  }
  const decrement = () => {
    setCount(count - 1)
  }
  const incrementNewCounter = () => {
    setNewCounter(newCounter + 1)
  }

  functionCounter.add(increment)
  functionCounter.add(decrement)
  functionCounter.add(incrementNewCounter)

  alert(functionCounter)

  return (
    <div>
      Count: {count}
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={incrementOtherCounter}>incrementNewCounter</button>
    </div>
  )
}

export default counterApp;

 

Output:

 

 

By updating the counter by 1,

 

 

The problem here is that each time the counter is updated, all three functions are recreated again. In the above example, you will see the alert incrementing by three at a time. 

You can see, if you increment one counter, all functions associated with it will be re-instantiated. But it should happen like if some state value is unchanged, it should not be touched. 

Generally, this does not create any problem. But if you are passing lots of different functions, this could affect the performance.

 

In that case, you can use useCallback.

const increment = (() => {
  setCount(count + 1)
})
const decrement = (() => {
  setCount(count - 1)
})
const incrementNewCounter = (() => {
  setNewCounter(newCounter + 1)
})

 

You wrap all those calls in:

const increment = useCallback(() => {
  setCount(count1)
}, [count])
const decrement = useCallback(() => {
  setCount(count1)
}, [count])
const incrementNewCounter = useCallback(() => {
  setNewCounter(newCounter1)
}, [newCounter])

 

Output:





 

 

 

 

By updating the counter by 1,

 

 

 

From the above output, we can see that the set size will increase by two because when we change the state 'count,' then only two functions will be re-instantiated. And when we update the state 'name,' then only one function will be re-instantiated so, the size of the set will increase by one only.

Now when we try to click one of the counters, only the functions related to that state will be re-instantiated. This will optimize the code and performance of the app.

Frequently Asked Questions-

 

  1. How many types of callbacks are there?

There are two types of callbacks based on data flow control at runtime: blocking callbacks (also known as synchronous callbacks) and deferred callbacks (also known as asynchronous callbacks).

2. Should I use useEffect or useCallback?

useCallback hook is used to memorize a callback, whereas useEffect produces side effects to some state changes. 

3. Why is the callback called callback?

A callback function is passed as an argument to another function, called from within the outer function to perform tasks. Hence, called "callback."

4. When should you not use useCallback?

You should avoid adding useCallback in every function. In most cases, it's better to accept that rendering creates new function objects.

Key takeaways-

 

In this blog, we learned about useCallback hook, its syntax, and its use. Then we learned about when to use this hook, and in the end, we discussed a few examples of both good and bad use of the useCallback() hook. 

 

We learned that if the performance increase is worth the complexity increase, we should use the useCallback() hook. Read more about hooks here. Learn more about useCallback() hook here.

 

By- Gazal Arora

 

Was this article helpful ?
0 upvotes

Comments

No comments yet

Be the first to share what you think