React.memo() is your friend
Tags: javascript, webdev, beginners, react
Published: 2021-12-22 21:44:32

`React.memo()` is one of those things that should be a part of every React developer's arsenal. It gives us the ability to memoize a React component. As with any tool, before we delve into how to use `React.memo()`, let's understand the problem first.

## Why memoize?

Memoization is a general concept which basically means caching the results of some kind of computation for later use. It is an optimization technique which is used quite extensively in the programming world.

> An important point to remember is that whenever memoization is used, there must be a criteria which would dictate when the cached results are no longer valid and the computation must be done again.

To understand the problem this solves, consider the following React component:

```js
import { useState, Fragment } from "react";

function App() {
  const [count, setCount] = useState(0);

  function handleDecrement() {
    setCount((oldCount) => --oldCount);
  }

  function handleIncrement() {
    setCount((oldCount) => ++oldCount);
  }

  return (
    <Fragment>
      <p>Count is {count}</p>
      <button onClick={handleDecrement}>-</button>
      <button onClick={handleIncrement}>+</button>
    </Fragment>
  );
}

export default App;
```

A simple component that keeps a count which can be increased or decreased.

![1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p13jvfr45rrj3013kx14.gif)
 
Now let's add another component to `<App />`. To keep it simple, we'll create a `<Message />` component that returns some kind of message depending on the `msgId` that is passed to it as a prop.

```js
function Message(props) {
  let msg = "hello, world";

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
}
```

We've kept it simple here but imagine this `<Message />` component does some heavy computation or perhaps sends a request to an external API in order to get the final message. We'll simulate this situation by adding everyone's favorite `console.log()` in the mix.

```js
function Message(props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
}
```

Let's update the `<App />` component to use `<Message />`.

```js
import { useState, Fragment } from "react";

function Message(props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
}

function App() {
  const [count, setCount] = useState(0);

  function handleDecrement() {
    setCount((oldCount) => --oldCount);
  }

  function handleIncrement() {
    setCount((oldCount) => ++oldCount);
  }

  return (
    <Fragment>
      <Message msgId={1} />
      <p>Count is {count}</p>
      <button onClick={handleDecrement}>-</button>
      <button onClick={handleIncrement}>+</button>
    </Fragment>
  );
}

export default App;
```

In the video below, take special note of the fact that every time `count` is changed, the heavy computation is done.

![2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wu8sf75tjyoc725qxm03.gif)
 
> To understand why the heavy computation is done every time `count` changes, check out this post: [Re-rendering in React](https://blog.bracketsinstitute.com/re-rendering-in-react)

At this point, take a step back and think about how inefficient our UI is at this moment. `count` does not affect `<Message />` in any way but still every time `count` is updated, the **seriously heavy computation** is performed. We only want the computation to occur if the `msgId` changes because a change in `msgId` should result in a different message.

## React.memo() to the rescue

`React.memo()` is a higher-order component. It accepts a component as its argument and memoizes the result. The memoized result is updated only if the props of the original component are changed.

To use `React.memo()`, simply pass your component as an argument and save the result. Our `<Message />` component will become:

```js
import { useState, Fragment, memo } from "react";

const Message = memo(function (props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
});
```

> Note: I've only imported `memo()` here. If you have `React` imported, you can use `React.memo()` instead of just `memo()`.

Now our code looks like this:

```js
import { useState, Fragment, memo } from "react";

const Message = memo(function (props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
});

function App() {
  const [count, setCount] = useState(0);

  function handleDecrement() {
    setCount((oldCount) => --oldCount);
  }

  function handleIncrement() {
    setCount((oldCount) => ++oldCount);
  }

  return (
    <Fragment>
      <Message msgId={1} />
      <p>Count is {count}</p>
      <button onClick={handleDecrement}>-</button>
      <button onClick={handleIncrement}>+</button>
    </Fragment>
  );
}

export default App;
```

This time, notice that the computation is done when the application is refreshed but the change in `count` no longer has that result.

![3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1tlaf8nqzanxlktx46dx.gif)
 
---

👉🏻 Subscribe to my newsletter: [click here](https://www.bracketsinstitute.com/newsletter-subscription)

👉🏻 Follow me on twitter: [click here](https://twitter.com/therealnrf)

---