Introduction to React.memo, useMemo and useCallback
Tags: react, tutorial
Published: 2019-11-06 18:38:57

## Prerequisite: Basic knowledge about [React](https://reactjs.org/)

> Cover photo by Danika Perkinson on Unsplash

When I start to write this blog, I ask myself whether I should only talk about the differences between **useMemo** and **useCallback** because they are React Hooks while **React.memo** is not. Eventually, I decided to include **React.memo** as well since on the one hand the word `memo` in both terminologies might sound a bit confusing for people. On the other hand, it's all about React optimization 😁

![optimization](https://user-images.githubusercontent.com/26871154/67630798-e9552e00-f895-11e9-88d9-d14f1efba456.jpg)

## 1. What is React.memo

If you are familiar with [React.PureComponent](https://reactjs.org/docs/react-api.html#reactpurecomponent) then **React.memo** is quite straightforward as it is exactly similar to **React.PureComponent**. We use **React.PureComponent** with class component while **React.memo** works with functional components 👌

Let's take a look at our example to see how it works. [Codesandbox](https://codesandbox.io/s/elated-mcnulty-f4zzo?fontsize=14)

> Note: All the examples below are used only to express the main ideas. In reality, we don't need optimization in such simple cases

```jsx
const App = () => {
	const [count1, setCount1] = React.useState(0)
	const [count2, setCount2] = React.useState(0)

	const increaseCounter1 = () => {
		setCount1(count1 => count1 + 1)
	}

	return (
		<>
			<button onClick={increaseCounter1}>Increase counter 1</button>
			<Counter value={count1}>Counter 1</Counter>
			<Counter value={count2}>Coutner 2</Counter>
		</>
	)
}
```

```jsx
const Counter = ({value, children}) => {
	console.log('Render: ', children)

	return (
		<div>
			{children}: {value}
		</div>
	)
}

export default Counter
```

Every time the user clicks on the button, the state of `count1` changes causing the App to rerender both counters which is known as **unnecessary re-render**. However, we expect only the **counter1** to be rerendered since nothing has changed with the **counter2**. In reality, both counters get rerendered. 

How can we address this issue? 🤔 Well, **React.memo** is our answer. All we need to do is to wrap our Counter component within **React.memo**

```jsx
const Counter = ({value, children}) => {
	console.log('Render: ', children)

	return (
		<div>
			{children}: {value}
		</div>
	)
}

export default React.memo(Counter)
```
By default, **React.memo** will compare all props passed to the component by **referential equality**. If these props are unchanged, **React.memo** will reuse the last rendered result, therefore, it prevents the component from being rerendered. In our example, **React.memo** will check if there are any changes with the `value` and `children` props since the last render. Since our button only changes the value of the **counter1**, **React.memo** will prevent the **counter2** from being rerendered. 😎💪

We can also override the default comparison of **React.memo** by providing a custom comparison function as the second argument. 

> From React.memo [documentation](https://reactjs.org/docs/react-api.html#reactmemo)
```
const Counter = () => {

   const areEqual = (prevProps, nextProps) => {
     /*
     return true if passing nextProps to render would return
     the same result as passing prevProps to render,
     otherwise return false
     */
   } 
}

export default React.memo(Counter, areEqual)
```

## 2. useMemo and useCallback

I will start with the documentation

> useMemo returns a memoized value
```
React.useMemo(() => {
  fooFunction()
}, [dependencies])
```

> useCallback returns a memoized callback
```
React.useCallback(() => {
  fooFunction()
}, [dependencies])
```

💪 Let's break it down together 

Both **React.useMemo** and **React.useCallback** receives a function as its first argument and a dependencies array as the second one. The hook will return a new value only when one of the dependencies value changes (referential equality). The main difference is that **React.useMemo** will call the `fooFunction` and return its result while **React.useCallback** will return the `fooFunction` without calling it. 

😫 Example please [codesandbox](https://codesandbox.io/s/vigorous-feather-jyr3w?fontsize=14)

```jsx
const App = () => {
	const fooFunction = () => {
		return 'Foo is just Food without D'
	}

	const useMemoResult = React.useMemo(fooFunction, [])
	const useCallbackResult = React.useCallback(fooFunction, [])

	console.log('useMemoResult: ', useMemoResult)
	console.log('useCallbackResult: ', useCallbackResult)

	return <p>Foo is just food without D</p>
}
```

If you run the code and take a look at your console, not refrigerator, you can see the following output

![use-memo-and-callback-result](https://user-images.githubusercontent.com/26871154/67631936-89668380-f8a5-11e9-84fe-36ac85912fc0.PNG)

**React.useMemo** runs the fooFunction which returns a string `Foo is just Food without D` while **React.useCallback** just returns a fooFunction without calling it

🤩 Got it. But how does it work in React?

### 🍀 useMemo
Normally we could use React.useMemo when we **compute expensive value** that we don't want to compute it again and again when the component is rerendered

```jsx
const Me = ({girlFriendWords}) => {

    // Provided that girlFriendWords is a string
	
	const myReply = decideWhatToSay (girlFriendWords)

	return <p>{myReply}</p>
}
```

Imagine that it takes full of my energy to calculate `myReply` value and what if I have to do it again and again (recalculate) when my girl friend says something (rerender) 🤐

🔥 **React.useMemo** comes to rescue

```jsx
const Me = ({girlFriendWords}) => {

    // Provided that girlFriendWords is a string
	
	const myReply = React.useMemo(() => decideWhatToSay (girlFriendWords), [girlFriendWords])

	return <p>{myReply}</p>
}
```

Thanks to **React.useMemo**, I couldn't have finished this blog without you 💑

**React.useMemo** takes `[girlFriendWords]` as its dependencies array which means that it will only run `decideWhatToSay ` function when `girlFriendWords` value changes. I don't have to think twice to reply when my girlfriend says the same thing. **Optimization here** 🎉🍀💐

![girlfriend-optimization](https://user-images.githubusercontent.com/26871154/67632288-3642ff80-f8aa-11e9-9a05-58d1a3a1f771.jpg)

### 🍀 useCallback

Enough relationship story, let's get back to our Counter example. Let's tweak the example a little bit, our counter now also receives `onClick` function as a prop. Could you guess whether our **Counter2** component will be rerendered when `count1` value change

```jsx
const App = () => {
	const [count1, setCount1] = React.useState(0)
	const [count2, setCount2] = React.useState(0)

	const increaseCounter1 = () => {
		setCount1(count1 => count1 + 1)
	}
	
	const increaseCounter2 = () => {
    		setCount1(count2 => count1 + 1)
    }

	return (
		<>
			<Counter value={count1} onClick={increaseCounter1}>Counter 1</Counter>
			<Counter value={count2} onClick={increaseCounter2}>Coutner 2</Counter>
		</>
	)
}
```

```jsx
const Counter = ({value, children, onClick}) => {
	console.log('Render: ', children)

	return (
		<Button onClick={}>
			{children}: {value}
		</div>
	)
}

export default React.memo(Counter)
```

The answer is **YES** 😮. 

Even when we use React.memo, the **counter2** component is still rerendered when only the `count1` changes because **React.memo** uses **reference equality** to prevent unnecessary renders. However, when App is rerendered, the `increaseCounter2` is recreated, therefore, the `onClick` props passed into the Counter component is different every time which causes the component to be rerendered. The easy way to avoid this issue is to prevent the `increaseCounter2` function from being recreated when the App is rerendered. 

We make use of **React.useCallback** to do this

```jsx
const App = () => {
	const [count1, setCount1] = React.useState(0)
	const [count2, setCount2] = React.useState(0)

	const increaseCounter1 = React.useCallback(() => {
		setCount1(count1 => count1 + 1)
	}, [])
	
	const increaseCounter2 = React.useCallback(() => {
    		setCount2(count2 => count1 + 1)
    }, [])
    
	return (
		<>
			<Counter value={count1} onClick={increaseCounter1}>Counter 1</Counter>
			<Counter value={count2} onClick={increaseCounter2}>Coutner 2</Counter>
		</>
	)
}
```

Take a look at the dependencies array, it's empty because I want to create these functions only once. In this way, the `onClick` props passed to the Counter component is always the same

## 3. Conclusion:
- 🚀 We should not optimize unnecessary rerenders without measuring the cost first. Optimization always comes with a cost
- 🚀 **React.memo** is similar to **React.PureComponent** except the fact that it is used for functional component while **React.PureComponent** is used only in class component
- 🚀 **React.useMemo** returns a memoized value while **React.useCallback** return a memoized callback

Here are some good resources for you:
- [Referential Equality](https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0)
- [React.memo documentation](https://reactjs.org/docs/react-api.html#reactmemo)
- [React.useMemo documentation](https://reactjs.org/docs/hooks-reference.html#usememo)
- [React.useCallback documentation](https://reactjs.org/docs/hooks-reference.html#usecallback)

## 🙏 💪 Thanks for reading!

*I would love to hear your ideas and feedback. Feel free to comment below!*

### ✍️ Written by

Huy Trinh 🔥 🎩 ♥️ ♠️ ♦️ ♣️ 🤓

Software developer | Magic lover

Say Hello 👋 on

✅ [Github](https://github.com/HuyAms)

✅ [LinkedIn](https://www.linkedin.com/in/huy-trinh-dinh-253534131/)

✅ [Medium](https://medium.com/@trnhnhhuy)