Let's Talk About Hooks - Part 2 (useLayoutEffect and useMemo)
Tags: react, javascript, beginners, webdev
Published: 2022-07-17 03:19:06

Salam and hello, folks!

Continuing the React Hook series, now I am going to talk about another 2 hooks, which are `useLayoutEffect` and `useMemo`. To the topic, we go!

But before that, I want to mention that these two are a rare hook, where you will only use them when there is a particular use case (even though I didn't encounter one yet). But don't worry, maybe you found this hook in your existing project and want to understand how these two hooks work. Well, I got you covered!

Let's start, shall we?

In this article, these are the topics covered:
1. [`useLayoutEffect` - Yet another lifecycle hook!](#section-1)
2. [The difference between `useEffect` and `useLayoutEffect`, and why it matters](#section-2)
3. [`useMemo` - The memoization hook](#section-3)
4. [When to not use `useMemo`](#section-4)
5. [Conclusion](#section-end)

---

## `useLayoutEffect` - Yet another lifecycle hook! <a name="section-1"></a>

In the previous article in this series, I explained how `useEffect` is one of the most used hook works. To simply put it a way to understand, it covers `componentDidMount` and `componentWillUnmount`. Well, `useLayoutEffect` does a lot of the same thing as `useEffect`, and in fact, the way you write `useLayoutEffect` is the same!

```jsx
useLayoutEffect(() => {
  // do your `componentDidMount` thing here
  return () => {
    // do your `componentWillUnmount` here
  };
}, [<all_dependencies_here>]);

useEffect(() => {
  // do your `componentDidMount` here
  return () => {
    // your `componentWillUnmount` here
  };
}, [<all_dependencies_here>]);
```

Welp, two hooks with quite similar names, with the same way to write them. What is the catch?

## The difference between `useEffect` and `useLayoutEffect`, and why it matters <a name="section-2"></a>

However, what difference does it make compared to `useEffect` then?

Well, need to know a key difference of "when" both of these hooks run. `useEffect` will run right after if there are any changes to any of the given dependencies to the hook, while `useLayoutEffect` will run after each change to the "layout", which means if there is a change to the DOM (DOM mutations). This includes if the change involves ref as well.

Not to be mistaken, you indeed supply the same array of dependencies to `useLayoutEffect` as you supplied to `useEffect`, but it will run after the DOM change, and if any of the dependency changes. Unlike `useEffect` which will run right after one of the dependencies changes.

So, when to use `useEffect` and when to use `useLayoutEffect`? Well, since `useEffect` is triggered as the dependencies change, `useEffect` is the hook you will use most of the time. `useEffect` is DOM independent, which means that DOM doesn't affect the behaviour of `useEffect`. Simply, `useEffect` is to **monitor state changes**.

`useLayoutEffect` triggers when there is a DOM mutation, so you can utilise that if you need to do some **DOM-related activities, such as measuring performance**, or detect DOM changes such as scroll position.

---

## `useMemo` - The memoization hook <a name="section-3"></a>

The fourth hook in this series is `useMemo`. This is for memoization. So what is memoization?

> In programming, memoization is an optimization technique that makes applications more efficient and hence faster. It does this by storing computation results in a cache and retrieving that same information from the cache the next time it's needed instead of computing it again. - Germán Cocca, freeCodeCamp

Memoization is an optimization technique, so your app becomes faster by utilising caches. Just imagine, you are calculating the value of infinity, so you don't want to run it every time the component rerenders, right?

```jsx
const [x, setX] = useState(0);
const valueOfInfinity = () => calculationOfInfinity(x);
```

Just imagine, this function will run EVERY TIME component rerenders 🥶

But first, let's see how useMemo is written, shall we?

```jsx
useMemo(() => {}, [array_of_deps]);

// example
const valueOfInfinity = useMemo(() => calculationOfInfinity(x), [x]);
```

The first part of the `useMemo` hook is the function you want to run. It could be an expensive function or something you want to keep a cache of the dependency. The expensive function here means that this requires a lot of resources to run the function.

The second part of the hook is the array of dependencies. And yes, it behaves similar to `useEffect`, where it will only run the function when one of the dependency change value.

Let's say we consider the example above. Just imagine the formula to calculate infinity is extremely complex, and it will surely consume a lot of resources each time the function runs, right? And adding to that, it depends on `x`, which possibly changes, since it is a state.

When you trigger `useState`, it will trigger the rerenders. When that happens, the function will run each time, even though the state value is unchanged. You could even trigger the `useState` to value "3" even though the value is already "3". But since `setState` is triggered, the component will rerender anyway.

We don't want that to happen. If the value of dependency is unchanged, we want to keep it that way and not trigger the function. So `useMemo` will hold the value of dependency and will observe the changes, so if the value is the same as the previous value, it won't run the function. So, even though we set `x` to 3, even though `x` is already equal to 3, the function won't run. Neat, right?

This can also be used to avoid children's rerenders too. Example:

```jsx
const TheButton = useMemo(() => <button>This button</button>, []);

// In your return
return () => (
  <TheButton />
);
```

In this example above, since you didn't add any dependency to the `<button>` component, it will only run once. Even though your parent component rerenders, `<TheButton>` won't rerender, since it will be the same throughout the component lifecycle. But of course, a simple component like the above example is too simple, and note that the component should be a pure component.

## When to not use `useMemo` <a name="section-4"></a>

Well, you just feel like "Hey, that means I can optimise everything by sprinkling `useMemo` everywhere in my code, right?

_Chotto matte!_ If you have this thought, you need to rethink your decision. Most of the time, `useMemo` make your app less optimised than you think!

```jsx
const [x, setX] = useState(0);
const [y, setY] = useState(1);
const theSum = useMemo(() => x + y, [x, y]);
```

Even if you can calculate x plus y using your fingers, why do you think your app needs to monitor changes for x and y, for the sake of adding x to y?

Most of the time, huge calculations are done by the backend, and the frontend will only retrieve the value from the API, and display it to the user.

So, to what level of complexity do you need to use `useMemo`? The answer is, **it is so rare** unless you need to calculate the value of infinity during rerenders. Personally, I didn't use `useMemo`, except for once, which is to calculate the effective interest rate of a loan based on several variables. Since that is a frontend-only app, so I had to use it. If you ask me, I do feel that the calculation might not need `useMemo` in the first place.

In case you are wondering [how to calculate effective interest rate](https://www.wikihow.com/Calculate-Effective-Interest-Rate).

---

## Conclusion <a name="section-end"></a>

That's it about `useLayoutEffect` and `useMemo`. Though they are hooks provided by React, the use case for them is not as easy as you think, thus the usage of these hooks is quite rare. At least, you know how to write them and how they work, so when you need to use these hooks by encountering the use case, you already know how to use them.

While `useMemo` is keeping the cache of its dependency for it to run the function, then what is `useCallback`? Well, keep yourself posted for the next article on the React hooks!

And as usual, take care of yourselves, and peace be upon ya!