React.memo(use me wisely)
Tags: react, javascript, codenewbie, reactnative
Published: 2020-08-16 12:29:49

`React.memo` is fairly simple but misunderstood High Order Component. By the docs we get this definition: 

> If your function component renders the same result given the same props, you can wrap it in a call to React.memo for a   performance boost in some cases by memoizing the result.    This means that React will skip rendering the component, and reuse the last rendered result.

**performance boost** 🤩? WOW, so let's memoize everything!

#### ⚠️ Calm down Sherlock, use it wisely.  

Let's have a deep look at what is the magic happening inside `memo` first when I said it is simple, you will have to agree after looking into the [code in the react repo](https://github.com/facebook/react/blob/41694201988c5e651f0c3bc69921d5c9717be88b/packages/react/src/ReactMemo.js). The entire code is basically this:

```javascript
const REACT_MEMO_TYPE = Symbol.for('react.memo');

export function memo<Props>(
  type,
  compare?: (oldProps: Props, newProps: Props) => boolean
) {
  const elementType = {
    $$typeof: REACT_MEMO_TYPE,
    type,
    compare: compare === undefined ? null : compare,
  };

  return elementType;
}
```

So this means that when you use it passing `SomeComponent` as to it you get as return basically: 

```javascript
  {
    $$typeof: Symbol.for('react.memo'),
    type: SomeComponent,
    compare: compare || null,
  }
```

This means that if you want to use this directly you will get the same result, don't believe me? Try it out in this [codesandbox](https://codesandbox.io/s/crazy-austin-rhibg?file=/src/App.js).

You can notice that there's a second parameter for `memo`, a `compare` function. Let's look into the docs again:

> By default it will only shallowly compare complex objects in the props object. If you want control over the comparison, you can also provide a custom comparison function as the second argument.

So this means that we can have the power to decide if the component should re-render even if the props might change. So let's say you never want your component to re-render again after the first time ( for whatever the reason you want to do that ), you can simply do this: 

```jsx
const MemoComponent = React.memo(({ name }) => {
  return <div>{name}</div>;
}, () => true);
```

⚠️ Notice that I am returning `true` in the compare function, I am basically saying that the meaningful previously props are the same as the next props so it should not re-render. ( It's basically the inverse of the `shouldComponentUpdate` )

So when to use it properly? Mainly you want to use it when your component is a pure functional component and/or it will always render with the same props and when you want to have control about if it should render or not. So, for example, imagine you have the following component: 

```jsx 
const UserInfoHeader = ({avatar, name}) => (
    <>
        <img src={avatar} />
        <div>Hi {name}</div>
    </>
)
```

And you gonna probably use it inside some dashboard, this is perfect opportunity to use `memo`, your dashboard may rerender and change several internal states but very unlikely to change the name or the avatar source, so wrapping the `UserInfoHeader` with React.memo will avoid unnecessary renders here.  

We have some better understanding now, but what is the problem if we wrap everything with `memo`? When it should be avoided? 

Using `memo` unwisely can lead you to bugs hard to debug and to the false feeling to be improving the performance. The question then is when **NOT** to use `React.memo`?

#### 1. Often props change 

`React.memo` has the cost to compare the props every render and if your components are updating the props all the time you are likely to lose performance since normal components wouldn't care about it and would just re-render normally.  

#### 2. Compare function is too expensive

Let's say you have a complex object being passed as prop and you want to make a very expensive calculation comparing the previous object with the new one. Heads up here, you might be also decreasing the performance than simple just re-rendering always. 

#### 3. Components with that receive functions as props

This is not a _don't_ but a _be careful_  when using callbacks in memoized components, for example:

```jsx
const Input = React.memo(...)

const App = () => (<Input onChange={(e) => { console.log(e) }} />)
```

In this case, the `Input` is going to be re-render all the time anyway because in each `App` render we will be redefining the `onChange` for the `Input` so either use static functions here or combine it with `useCallback` to prevent it to happen. 

------
### Wrapping up

`React.memo` is a powerful and easy to use HOC to gain performance but the misusage can backfire and actually harm the performance. Try to always be careful with it and use some profiling tools to make sure about the valid use cases.

Do you have an example of good usage for `memo` or have you faced some bug because of it? Share with us in the comments. :)