Introduction to useCallback() Hook In ReactJS

Introduction

In the previous article, we have learned about using useReducer() hook and how it is used in React. Now, in this article, we will learn about the importance of useCallback() hook and why this hook is required.

useCallback() hook

In React, useCallback() hook is another important hook which is used for performance optimization. When we implement or call any component, all components re-render every time any call is made.

For a small application, it will not have much effect. But when dealing with a large application, it will give performance issues. So, useCallback() provides a way to render components only when required. 

Let’s look at the demo.

Create 4 components. 

Title.js

import React from 'react'  
  
function Title() {  
    console.log("Title component rendered")  
    return (  
  
        <div>  
            React Title  
        </div>  
    )  
}  
  
export default Title   

Button.js

import React from 'react'  
  
function Button({count,handleClick}) {  
  
    console.log("Button Component rendered")  
    return (  
        <div>  
            <p>Counter : {count}</p>  
            <button onClick={handleClick}>Increment Counter</button>  
        </div>  
    )  
}  
  
export default Button 

Textbox.js

import React from 'react'  
  
function Textbox({name,handleClick}) {  
    console.log("Textbox Rendered")  
    return (  
        <div>  
            <input type="text" placeholder="Enter Name" value={name} onChange={handleClick}/>  
        </div>  
    )  
}  
  
export default Textbox   

Parent.js

import React, { useState } from 'react';  
import Title from './components/Title';  
import Button from './components/Button';  
import Textbox from './components/Textbox';  
  
function Parent() {  
  
  const [count, setCount] = useState(0)  
  const [name, setName] = useState("")  
  
  const incrementCounter = () => {  
    setCount(count + 1)  
  }  
  
  const updateName = (e) => {  
    setName(e.target.value)  
  }  
  
  return (  
    <div className="App">  
      <Title />  
  
      <Button count={count} handleClick={incrementCounter} />  
        
      <label>Name is {name}</label>  
      <Textbox text={name} handleClick={updateName} />  
    </div>  
  );  
}  
  
export default Parent;

The output will be displayed as below. 

Initially, it will render as below.

useCallback() Hook In ReactJS

On click of a button, we can check in the console that all components are rendered again even if there is the change in a single component.

useCallback() Hook In ReactJS

Now, the same – even if a change in a textbox is made, all components are rendered again.

useCallback() Hook In ReactJS

So, to avoid the rerendering of components, there is a need for useCallback(). 

Now, while the exporting component adds React.Memo() function, it will render only if there will be a change in props or state. 

Title.js

import React from 'react'  
  
function Title() {  
    console.log("Title component rendered")  
    return (  
  
        <div>  
            React Title  
        </div>  
    )  
}  
  
export default React.memo(Title) 

Button.js

import React from 'react'  
  
function Button({count,handleClick}) {  
  
    console.log("Button Component rendered")  
    return (  
        <div>  
            <p>Counter : {count}</p>  
            <button onClick={handleClick}>Increment Counter</button>  
        </div>  
    )  
}  
  
export default React.memo(Button) 

Textbox.js

import React from 'react'  
  
function Textbox({name,handleClick}) {  
    console.log("Textbox Rendered")  
    return (  
        <div>  
            <input type="text" placeholder="Enter Name" value={name} onChange={handleClick}/>  
        </div>  
    )  
}  
  
export default React.memo(Textbox) 

Now, check the output. Initially, it will render all 3 components.

useCallback() Hook In ReactJS

After clicking on the button, the Title component will not be rendered.

useCallback() Hook In ReactJS

So, to resolve the issue of the re-rendering components, if there is no change in the component useCallback() hook is used. 

useCallback() hook will return a memorized version of the callback function that will change only when dependencies have changed. It is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders. 

Now add callback function in Parent.js

import React, { useState,useCallback } from 'react'  
import Title from './Title';  
import Button from './Button';  
import Textbox from './Textbox';  
  
function Parent() {  
    const [count, setCount] = useState(0)  
    const [name, setName] = useState("")  
    
    const incrementCounter = useCallback(() => {  
      setCount(count + 1)  
    },[count])  
    
    const updateName = useCallback((e) => {  
      setName(e.target.value)  
    },[name])  
    
    return (  
        <div>  
            <Title />  
            
            <Button count={count} handleClick={incrementCounter} />  
            <label>Name is {name}</label>  
            <Textbox text={name} handleClick={updateName} />  
        </div>  
    )  
}  
  
export default Parent  

The output will be displayed as below.

useCallback() Hook In ReactJS

Now, on typing in textbox, the textbox component is rendered.

useCallback() Hook In ReactJS

So, this way, we can optimize performance. useCallback() hook provides an efficient way to write code and organize components by rendering a component only when it is required which also provide performance improvement and code optimization.

It is used with React.memo() which makes sure that the no extra render should be performed unnecessarily. So, this way the complete flow works. 

Summary

In this article, we have learned about useCallback() hook and how to use it. In the next article, we will learn about useMemo() hook and its use in ReactJS.

Any question or feedback or suggestion, please do comment and let me know.

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s