React hooks: useMemo
Tags: react, hooks, webdev, javascript
Published: 2022-11-11 10:54:24

If you are working with React, you have probably heard about the term **useMemo**.
In a nutshell, `useMemo` is a built-in React hook that allows you to **memoize output of a function** to prevent it from re-running on every component re-render.

So, we could say, the goal of `useMemo` hook is to provide a simple way to achieve gains in performance using memoization. But, there is more to it, so let's dive deeper.

## How it works

This hook has the following signature.

```javascript
const memoizedValue = useMemo(compute, dependencies);
```

You can see that `useMemo` accepts 2 arguments.

- `compute` - function used to compute a result.
- `dependencies` - array of dependencies used by `compute` function.

On the initial render of the component, `useMemo` will invoke the `compute` function, memoize the result of the `compute` function and return the value.

On every component re-render, `userMemo` will check if `dependencies` are changed. If change is detected, `useMemo` will invoke the `compute` function again, otherwise it will return previously memoized value.

---
In programming, memoization is usually implemented in a way that memoization function **remembers all inputs** and results based on those inputs. Next time, when the same inputs are sent to the memoization function, it will return memoized result.

On the other hand, **useMemo only remembers previous inputs** and results based on those inputs. As soon as next inputs are not the same as previous inputs, useMemo will run the computation again.

---

## When should it be used

Thing is, `useMemo` does not give free performance gains. Running `useMemo` will consume **CPU time and memory** which can hurt performance if used incorrectly.

For this reason, `useMemo` should not be used everywhere whenever possible, but rather in some situations where memoization would provide performance benefits.

Overall, make sure that your component does not depend on `useMemo` at all. Only if you notice performance issues, introduce `useMemo`. Here are some questions you can ask yourself to decide if `useMemo` should be used.

1. Is the component running expensive calculations?
2. Is the component re-rendering often?
3. Is the component doing data transformation?

There is no guideline which will tell you when exactly to use this hook. You need to make sure that you understand the problem you are having and then, you will know if `useMemo` can help you.

## Show me some code

It is true that usage of `useMemo` hook may vary and depend on your component, but it is still possible to provide some examples where `useMemo` would make sense and where not.

### Bad case

As the first example, let's say we want to calculate user age based on the year of birth and the current year. While at it, you might want to add `useMemo` there, you know, just in case.

```javascript
const userAge = useMemo(
  () => currentYear - yearOfBirth,
  [currentYear, yearOfBirth]
);
```

Well, there you go, this is a bad usage of the `useMemo` hook. Computers are fast and doing simple calculations like this will take basically no time. Just do the following instead.

```javascript
const userAge = currentYear - yearOfBirth;
```

---
When doing calculations on primitive values like numbers, strings, booleans, never wrap them with useMemo. It can **take longer** to execute useMemo than the calculation itself.

---

### Good case

In this example, there is a function that takes an array of users and formats the activities for every user. Additionally, alongside activities, we want to return users' full name and age.

```javascript
const activitiesPerUser = useMemo(() => {
  return users.map((user) => {
    return {
      fullName: `${user.firstName} ${user.lastName}`,
      age: user.age,
      activities: formatUserActivities(user),
    };
  });
}, [users]);
```

This function might take a lot of time if formatting of activities is complicated or if the `users` array is large. In this case, it makes sense to wrap the function in the `useMemo` hook, especially if the component gets re-rendered multiple times with the same `users` object.

---
Memoize results of functions that are doing **expensive calculations and data transformations**. Even if component is not being re-rendered at all, it is still good to wrap those functions with useMemo.

---

## Conclusion

Oh, congrats, you made it to the end. I hope that the `useMemo` hook is not as complicated anymore.

From my experience, it is always worth memoizing computed non-primitive values, like arrays or objects, that are passed down to the child components. It is even more important if the parent component hosts state variables that are frequently changed. This can prevent unnecessary re-renders of child components.

In general, do not think about performance optimization too much. If your application is not performant, don't worry, you will notice it.

---

This post was first published on [my blog](https://ramomujagic.com/blog/react-hooks-usememo/).