useCallback and useMemo hooks. What are they and how do you use them?
Tags: react, webdev
Published: 2020-07-09 15:49:31

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/u7dz8w3312yprziy2jhz.png)

This article is part of the **React hooks series**. If you haven't read the other articles, you can find them at the links below.

<ol>
   <li> <a href = "https://dev.to/nibble0101/what-is-useeffect-hook-and-how-do-you-use-it-1p9c"> What is useEffect hook and how do you use it? </a></li>
  <li> <a href = "https://dev.to/nibble0101/what-is-usereducer-hook-and-how-do-you-use-it-3j83"> What is useReducer hook and how do you use it?</a></li>
  <li> <a href = "https://dev.to/nibble0101/what-is-usestate-hook-and-how-do-you-use-it-3d71"> What is useState hook and how do you use it? </a></li>
</ol>

<h1> Content outline </h1>
<ol>
 <li> <a href = "#use-callback"> useCallback hook </a> </li>
 <li> <a href = "#use-memocallback">useMemo hook </a> </li>
 <li> <a href = "#references">References </a> </li>
</ol>


<h1 id = "use-callback"> useCallback hook </h1>

A hook is a special function which enables one use state and  other react features without writing ES6 class components, according to [React hooks documentation](https://reactjs.org/docs/hooks-reference.html). 
The `useCallback` hook is part of the React Hooks API. It takes a callback function and an array of dependencies as arguments. It returns a memoized version of the function passed as argument. If the above definition doesn't make sense, the sections below explain what is `useCallback` hook, why it is important and how to use it. 

In the code below, i have defined two event handlers; `eventHandler` which we shall later pass as a prop to `Child` component and `clickHandler` which is attached as a click event handler on the button element. In React, a component is re-rendered if its state or props change leading to a re-render of its descendants too. For this particular case if we change state of `App`, its child component `Child` will also re-render. To prevent `Child` component from re-rendering if its parent's state changes, i used `React.memo`. If you are not familiar with `React.memo`, you can read about it [Here](https://reactjs.org/docs/react-api.html). If you now click the button, it will fire the event handler `clickHandler` which will change state of `App`. You will see `Parent is rendered` on the console but not `Child is rendered`.  If we hadn't wrapped `Child` component in `React.memo`, changing state of `App` would make `Child` component to be re-rendered but this has been prevented by `React.memo`.  This way we can be sure that `Child` component is only re-rendered due to change in props. You can play with the code [Here]( https://codepen.io/nibble0101/pen/eYJrLGj) on Codepen.

```javascript
import React from "react";
import ReactDOM from "react-dom";

const App = (props) => {
  const [state, setState] = React.useState(0);
  const eventHandler = (e) => {
    console.log(1);
  };
  const clickHandler = (e) => {
    setState((prevState) => prevState + 1);
  };
  console.log("Parent is rendered");
  return (
    <div>
      <button onClick={clickHandler}> click </button>
      <Child />
    </div>
  );
};

const Child = React.memo((props) => {
  console.log("Child is rendered");
  return null;
});

const root = document.getElementById("root");
ReactDOM.render(<App />, root);


```
 You can play with the above code [Here]( https://codepen.io/nibble0101/pen/eYJrLGj) on Codepen.



Let us now pass `eventHandler` as a prop to `Child` component. Change only one line: ` <Child />`. Pass `eventHandler` as prop so that we have `<Child eventHandler={eventHandler} />`.
The above code becomes:

```javascript
import React from "react";
import ReactDOM from "react-dom";


const App = (props) => {
  const [state, setState] = React.useState(0);
  const eventHandler = (e) => {
    console.log(1);
  };
  const clickHandler = (e) => {
    setState((prevState) => prevState + 1);
  };
  console.log("Parent is rendered");
  return (
    <div>
      <button onClick={clickHandler}> click </button>
      <Child eventHandler={eventHandler} />
    </div>
  );
};

const Child = React.memo((props) => {
  console.log("Child is rendered");
  return null;
});

const root = document.getElementById("root");
ReactDOM.render(<App />, root);

```
You can play with the above code [Here](https://codepen.io/nibble0101/pen/JjGvmEG?editors=1111) on Codepen.

If you change state of `App` by clicking the button, `Child` component will also be re-rendered. Both `Parent is rendered` and `Child is rendered` will be *console logged*. Before passing `eventHandler` to `Child` as a prop, a re-render of `App` doesn't cause a re-render of `Child` but after passing `eventHandler` as a prop, `Child` is re-renderd. This happens because a re-render of `App` creates a new instance of `eventHandler`, which has been passed as prop to `Child`. React will compare instance of `eventHandler` created for the previous render and for current render. The two won't be equal because a function is an object and two objects tested for equality (strict or non-strict) will only evaluate to true if they have the same reference. For example `{} === {}`, `[] === []` and `function(){} === function(){}` will all evaluate to false. Strictly speaking, React uses `Object.is` algorithm to compare `eventHandler`. This is interpreted by React as change in props resulting in a re-render of `Child`. This, most likely, is not what you need.

The above behaviour is, in most cases, undesirable. As a result `useCallback` was developed to fix such problems. It takes a function and array of dependencies as argument. If you pass an empty array, React will always return the same memoized instance of function passed as argument.  If an event handler is passed as an argument to `useCallback`, the same version of the callback is returned in subsequent renders as long as array of dependencies haven't changed. Change `eventHandler` to:
```javascript
   const eventHandler = React.useCallback((e) => {
    console.log(1)
  }, [])
```
If you now change state of `App`, `Child` component will not be re-rendered. I hope you notice the empty array passed as second argument. It will ensure the same memoized version of the callback is returned between renders. If you pass an array of dependencies, different memoized version is returned whenever the dependencies change between renders. It should be noted that any value referenced within the callback function (first argument to `useCallback`) should be passed as a dependency.

<h1 id = "use-memocallback">useMemo hook </h1>

In the above section, we looked at what `useCallback` hook is and how to use it. It is now time to look at another hook closely related to `useCallback`, `useMemo`. The function signature of `useMemo` is similar to that of `useCallback`. The difference is that `useMemo` returns a memoized value while `useCallback` returns a `memoized` callback function. Both take a function as first argument and an array of dependencies as second argument.
`useMemo` hook is used for performing operations which are computationally expensive (Takes a long time to perform or a lot of computer memory). If the dependencies do not change, `memoized` value will always be returned. If you want the computation to be performed once then pass an empty array. 

The code below illustrates how `useMemo` hook is used.

```javascript
const App = (props) => {
  const [count, setCount] = React.useState(0);
  const memoizedValue = React.useMemo(() => {
    return Math.random(); //This should be an expensive computation not just generating a random number
  }, []);
  console.log(memoizedValue);
  const clickHandler = (e) => {
    setCount(count + 1);
  };
  return (
    <p>
      <button onClick={clickHandler}> Click </button>
    </p>
  );
};

const root = document.getElementById("root");

ReactDOM.render(<App />, root);

```
You can play with the above code [Here](https://codepen.io/nibble0101/pen/WNrJYwV?editors=1111) on Codepen.

In the code above, i passed a function which generates and returns a random number(ONLY for illustration). Since i passed an empty array as a dependency, the first random number is memoized and returned on every re-render of the component. If i had not passed a dependency, the random value is computed on every render of the component. The value returned is computed again if the dependencies change
 
**Note**
> You are strongly advised against using `useMemo` hook willy-nilly. `useMemo` hook is used if you are peforming an expensive computation. Do not use it for generating random number like i did in the example. It is meant to illustrate how to use `useMemo` hook. 

Thanks for reading up to the end. If you find anything technically inaccurate, you can comment below and if you find the article enlightening, share it on [Twitter](https://twitter.com/) or any other social media platform/community. Others might find it useful too.

<h1 id = "references"> References </h1>

<ol>
 <li> <a href = "https://reactjs.org/docs/hooks-intro.html"> React Hooks API </a> </li>
 <li> <a href = "https://stackoverflow.com/questions/54371244/what-is-the-intention-of-using-reacts-usecallback-hook-in-place-of-useeffect"> Stackoverflow </a> </li>

</ol>