ReactJS - useCallback



The useCallback hook is similar to useMemo hook and provides the functionality of memoizing the function instead of values. Since callback function in an integral part of the JavaScript programming and callback functions are passed by references, react provides a separate hook, useCallback to memoize the callback functions. In theory, useCallback functionality can be done using useMemo hook itself. But, useCallback improves the readability of the react code.

Signature of the useCallback hook

The signature of the useCallback hook is as follows −

const <memoized_callback_fn> = useCallback(<callback_fn>, <dependency_array>);

Here, the useCallback accepts two input and returns a memoized callback function. The input parameter are as follows −

  • callback_fn − Callback function to be memorized.

  • dependency_array − Hold variables, upon which the callback function depends.

The output of the useCallback hook is the memoized callback function of the callback_fn. Usage of useCallback hook is as follows −

const memoizedCallbackFn = useCallback(() => {
   // code
}, [a, b])

Note − The useCallback(callback_fn, dependency_array) is equivalent to useMemo(() => callback_fn, dependency_array).

Applying useCallback

Let us learn how to apply the useCallback hook by creating a react application.

First of all, create and start a react application by using create-react-app command as shown below −

create-react-app myapp
cd myapp
npm start

Next, create a component, PureListComponent under components folder (src/components/PureListComponent.js)

import React from "react";
function PureListComponent() {
   return <div>List</div>
}
export default PureListComponent

Next, update the root component with PureListComponent component as shown below −

import PureListComponent from './components/PureListComponent';
function App() {
   return (
      <div style={{ padding: "5px" }}>
         <PureListComponent />
      </div>
   );
}
export default App;

Next, open PureListComponent.js and add two props

  • list of items to show in the component

  • callback function to show the item clicked by user in the console

import React from "react";
function PureListComponent(props) {
   const items = props['items'];
   const handleClick = props['handleClick']
   console.log("I am inside the PureListComponent")
   return (
      <div>
         {items.map((item, idx) =>
            <span key={idx} onClick={handleClick}>{item} </span>
         )}
      </div>
   )
}
export default React.memo(PureListComponent)

Here we have,

  • Used items props to get the list of items

  • Used handleClick to get the handler for click event

  • Wrapped the component using React.memo to memoize the component. Since the component will render same output for the given set of input, it is called PureComponent in react.

Next, let us update App.js and use the PureListComponent as shown below −

import React, {useState, useEffect} from 'react';
import PureListComponent from './components/PureListComponent';
function App() {
   
   // array of numbers
   var listOfNumbers = [...Array(100).keys()];
   
   // callback function
   const handleCallbackFn = (e) => { console.log(e.target.innerText) }
   const [currentTime, setCurrentTime] = useState(new Date())
   useEffect(() => {
      let interval = setInterval(() => {
         setCurrentTime(new Date())
      }, 1000)
      return () => clearInterval(interval)
   }, [currentTime])
   return (
      <div style={ { padding: "5px" } }>
         <PureListComponent items={listOfNumbers} handleClick={handleCallbackFn}/>
         <div>Time: <b>{currentTime.toLocaleString().split(',')[1]}</b></div>
      </div>
   );
}
export default App;

Here we have Included a state, currentTime and updated it every second using setInterval to make sure the component rerenders every second.

We may thought that PureListComponent will not rerender every second as it uses React.memo. But, it will rerender as the props value are of reference type.

Next, update the root component and use useMemo and useCallback to preserve the array and callback function as shown below −

import React, {useState, useEffect, useCallback, useMemo} from 'react';
import PureListComponent from './components/PureListComponent';
function App() {
   
   // array of numbers
   const listOfNumbers = useMemo(() => [...Array(100).keys()], []);
   
   // callback function
   const handleCallbackFn = useCallback((e) => console.log(e.target.innerText), [])
   const [currentTime, setCurrentTime] = useState(new Date())
   useEffect(() => {
      let interval = setInterval(() => {
         setCurrentTime(new Date())
      }, 1000)
      return () => clearInterval(interval)
   }, [currentTime])
   return (
      <div style={ { padding: "5px" } }>
         <PureListComponent items={listOfNumbers} handleClick={handleCallbackFn}/>
         <div>Time: <b>{currentTime.toLocaleString().split(',')[1]}</b></div>
      </div>
   );
}
export default App;

Here we have,

  • Used useMemo to preserve the items array

  • Used useCallback to preserve the handleClick callback functions

Finally, check the application in the browser and it will not rerender PureListComponent every second.

Signature of the UseCallback Hook

Use cases of useCallback

Some of the use cases of the useCallback hook is as follows −

  • Pure functional component with function props

  • useEffect or other hooks having function as dependency

  • Usage of function during debouncing / throttling or similar action

Advantages

Advantages of useCallback hook are as follows −

  • Simple to use API

  • Easy to understand

  • Improves the performance of the application

Disadvantages

Technically, useCallback have no disadvantages. But, heavy usage of useCallback in a application will bring below disadvantages.

  • Decrease the readability of the application

  • Decrease the Understandability of the application

  • Debugging the application is complex

  • Developer should have deep understanding of JavaScript language to use it

Summary

useCallback is easy to use and improves performance. At the same time, useCallback should be used only when it is absolutely necessary. It should not be used in every scenario. The general rule is check the performance of the application. if it needs improvement, then we can check whether the usage of useCallback will help to improve the performance. If we get positive response, then we can use it. Otherwise, we can leave it to the react to improve and optimize the performance of the application.

Advertisements