React `UseMemo`
Tags: react, usememo, webdev, programming
Published: 2023-04-25 07:08:53

## What is `useMemo`?

> `useMemo` is a React Hook that lets you cache the result of a calculation between re-renders.

Typically, `useMemo` reduces the amount of work that needs to be done in a given render. `useMemo` can memoize the function and its result, meaning that if the inputs of the function do not change, React will return the memoized value instead of recomputing it, which will potentially speed up your render process.

## A Simple Explanation

Let's say we have a really slow function which takes up huge amount of time to computer in the render process:

```js
// a really slow function...
const slowFunction = (num) => {
  for (let i = 0; i < 1000000000; i++) { }
  return num * 2;
}
```

And we need the result of this `slowFunction` for rendering the webpage, for example, the `complexResult` variable:

```js
const complexResult = slowFunction(input);
```

```js
<p> { complexResult } </p>
```

In this case, calling `slowFunction` in every render will significantly slow down your application. This is where `useMemo` comes in handy.

We can wrap the `slowFunction` inside `useMemo` and provide an array of dependencies. The array of dependencies is used to determine whether or not the memoized value should be recalculated. If any of the dependencies change, `useMemo` will recalculate the memoized value, or it will just use the previous "memoized" value.

A simple metaphor would be:

- if I'm solving the puzzle for the first time, I have to take time to go through every steps until I solve it and give the answer.
- If you ask me to solve the same puzzle the second time, I don't have to go through all the steps once again. Instead, I just give you the answer directly because it's already in my brain.
- If you ask me to solve another different puzzle, I still have to take time to go through every steps.

Here:

- the process of solving the puzzle is the `slowFunction`
- the answer is the `complexResult`
- the puzzle problem is the `dependency`.

## How to use `useMemo`?

The prototype is given as follows:

```js
const cachedValue = useMemo(calculateValue, dependencies);
```

where

- `calculateValue`: The function calculating the value that you want to cache. (typically slow functions)
- `dependencies`: The list of all reactive values referenced inside of the calculateValue code
- `cachedValue`: the same result of calling calculateValue

Back to our example, previously we have:

```js
const complexResult = slowFunction(input);
```

And with `useMemo`, this line could be changed into:

```js
const complexResult = useMemo(() => {
  return slowFunction(input)
}, [input])
```

In the example above, `complexResult` will only be recalculated if the `input` dependency changes. If `input` stays the same, React will return the previously memoized value, which saves us from calling `slowFunction` again and again.

## A Complete Example

In case you still find this concept abstract or just need some contexts to think over. A slightly more complex example is provided below.

### Without `useMemo`

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

const slowFunction = (num) => {
  console.log("running slow double calculation...");
  for (let i = 0; i < 1000000000; i++) {}
  return num * 2;
};

const Demo = () => {
  const [number, setNumber] = useState(0);
  const [color, setColor] = useState("black");

  const doubledNumber = slowFunction(number);

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <button onClick={() => setColor(color === "black" ? "green" : "black")}>
        Change Color!
      </button>
      <p style={{ color: color }}>{doubledNumber}</p>
    </div>
  );
};

export default Demo;
```

What just happened after clicking the change color button?

1. `setColor` triggered re-render
2. Recalculate `doubledNumber` takes lots of time
3. Lead to slow render of `doubledNumber`  

### With `useMemo`

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

const slowFunction = (num) => {
  console.log("running slow double calculation...");
  for (let i = 0; i < 1000000000; i++) {}
  return num * 2;
};

const Demo = () => {
  const [number, setNumber] = useState(0);
  const [color, setColor] = useState("black");

  const doubledNumber = useMemo(() => {
    return slowFunction(number);
  }, [number]);

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <button onClick={() => setColor(color === "black" ? "green" : "black")}>
        Change Color!
      </button>
      <p style={{ color: color }}>{doubledNumber}</p>
    </div>
  );
};

export default Demo;
```

Thanks to `useMemo`, we no longer have to wait for a long time for setting color after changing the number. 

## Reminder: Don’t use `useMemo` everywhere!

The reasons are:

- Overusing `useMemo` can hurt performance and introduce unnecessary overhead.
- Memoization is most effective for **expensive computations** that produce the same output for the same inputs.
- Overusing `useMemo` can make your code harder to read and maintain.

## Reference

1. useMemo. React. (n.d.). Retrieved April 25, 2023, from https://react.dev/reference/react/useMemo