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
  1. import React from 'react'  
  2.   
  3. function Title() {  
  4.     console.log("Title component rendered")  
  5.     return (  
  6.   
  7.         <div>  
  8.             React Title  
  9.         </div>  
  10.     )  
  11. }  
  12.   
  13. export default Title   
Button.js
  1. import React from 'react'  
  2.   
  3. function Button({count,handleClick}) {  
  4.   
  5.     console.log("Button Component rendered")  
  6.     return (  
  7.         <div>  
  8.             <p>Counter : {count}</p>  
  9.             <button onClick={handleClick}>Increment Counter</button>  
  10.         </div>  
  11.     )  
  12. }  
  13.   
  14. export default Button   
Textbox.js
  1. import React from 'react'  
  2.   
  3. function Textbox({name,handleClick}) {  
  4.     console.log("Textbox Rendered")  
  5.     return (  
  6.         <div>  
  7.             <input type="text" placeholder="Enter Name" value={name} onChange={handleClick}/>  
  8.         </div>  
  9.     )  
  10. }  
  11.   
  12. export default Textbox   
Parent.js
  1. import React, { useState } from 'react';  
  2. import Title from './components/Title';  
  3. import Button from './components/Button';  
  4. import Textbox from './components/Textbox';  
  5.   
  6. function Parent() {  
  7.   
  8.   const [count, setCount] = useState(0)  
  9.   const [name, setName] = useState("")  
  10.   
  11.   const incrementCounter = () => {  
  12.     setCount(count + 1)  
  13.   }  
  14.   
  15.   const updateName = (e) => {  
  16.     setName(e.target.value)  
  17.   }  
  18.   
  19.   return (  
  20.     <div className="App">  
  21.       <Title />  
  22.   
  23.       <Button count={count} handleClick={incrementCounter} />  
  24.         
  25.       <label>Name is {name}</label>  
  26.       <Textbox text={name} handleClick={updateName} />  
  27.     </div>  
  28.   );  
  29. }  
  30.   
  31. 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
  1. import React from 'react'  
  2.   
  3. function Title() {  
  4.     console.log("Title component rendered")  
  5.     return (  
  6.   
  7.         <div>  
  8.             React Title  
  9.         </div>  
  10.     )  
  11. }  
  12.   
  13. export default React.memo(Title)  
Button.js
  1. import React from 'react'  
  2.   
  3. function Button({count,handleClick}) {  
  4.   
  5.     console.log("Button Component rendered")  
  6.     return (  
  7.         <div>  
  8.             <p>Counter : {count}</p>  
  9.             <button onClick={handleClick}>Increment Counter</button>  
  10.         </div>  
  11.     )  
  12. }  
  13.   
  14. export default React.memo(Button)  
Textbox.js
  1. import React from 'react'  
  2.   
  3. function Textbox({name,handleClick}) {  
  4.     console.log("Textbox Rendered")  
  5.     return (  
  6.         <div>  
  7.             <input type="text" placeholder="Enter Name" value={name} onChange={handleClick}/>  
  8.         </div>  
  9.     )  
  10. }  
  11.   
  12. 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
  1. import React, { useState,useCallback } from 'react'  
  2. import Title from './Title';  
  3. import Button from './Button';  
  4. import Textbox from './Textbox';  
  5.   
  6. function Parent() {  
  7.     const [count, setCount] = useState(0)  
  8.     const [name, setName] = useState("")  
  9.     
  10.     const incrementCounter = useCallback(() => {  
  11.       setCount(count + 1)  
  12.     },[count])  
  13.     
  14.     const updateName = useCallback((e) => {  
  15.       setName(e.target.value)  
  16.     },[name])  
  17.     
  18.     return (  
  19.         <div>  
  20.             <Title />  
  21.             
  22.             <Button count={count} handleClick={incrementCounter} />  
  23.             <label>Name is {name}</label>  
  24.             <Textbox text={name} handleClick={updateName} />  
  25.         </div>  
  26.     )  
  27. }  
  28.   
  29. export default Parent  
The output will be displayed as below.
 
useCallback() Hook In ReactJS
 
Now, on click of a button, only the button component is rendered.
 
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. You can download the source code attached along with this article. In the next article, we will learn about useMemo() hook and its use in ReactJS.