React useMemo. A Beginner, straightforward, and simple explanation.

React useMemo. A Beginner, straightforward, and simple explanation.

Basic React knowledge, JavaScript arrow functions...

Let's face it: It's always a pain when things take ages to load or break by simply typing, right?

Despite React already being amazing when it comes to performance, as they say:

Internally, React uses several clever techniques to minimize the number of costly DOM operations required to update the UI.

With the introduction of React Hooks, we can take performance to the next level!!!

Let's take the following code as an example:

import React, { useState } from 'react';

export default function Checkout() {
  const [clientName, setClientName] = useState('');
  const [numApples, setNumApples] = useState(0);
  const doubledApples = handleDoubleApples(numApples);

  return (
    <>
      <input 
        type="text" 
        value={clientName} 
        onChange={(e) => setClientName(e.target.value)}>
      </input>

      <button onClick={() => setNumApples(numApples + 1)}>
        Add apple
      </button>

      <h1>Client has {numApples} apples.</h1>
    </>
  );
}

function handleDoubleApples(numApples) {
  console.log("Deciding if should give more apples.....");

  // Let's imagine this as a very expensive function.
  // And needs to run to give the client more apples.
  for (let i = 0; i < 1000000000; i++) {} 

  console.log("Okay, let's give more apples!");
  return numApples * 2;
}

Let's break down the code above:

  1. Our first state will contain the name of our client.
  2. The second will be the number of apples.
  3. We will give our client some extra apples, so our handleDoubleApples will contain the total amount of apples.
  4. We have a button to add the number of apples the client has in the bucket.

Simple, right?

Well, yes. But every time we type a letter of the client's name, our handleDoubleApples will re-run and, as we can see, it is a very slow function which will loop 100.000.000 times 🤯🤯.

So, the question we need to ask ourselves is:

Well, I don't think that this function should be re-run every time I change the client name. How can I prevent this from happening?

That's when our useMemo() comes in handy. Let's do it then:

First, let's import it to our file:

import React, { useState, useMemo } from 'react';

Now, we just need to wrap our handleDoubleApples with a useMemo():

const doubledApples = useMemo(() => {
  return handleDoubleApples(numApples)
}, [numApples]);

Breaking down what we just did here:

1 - useMemo() needs to have 2 params inside of it. useMemo(function, array).

2 - The first param is a function that will return the value we a trying to "memoize".

3 - The second param is an array of dependencies. Which our hook will look for when deciding if it should re-render the value or not. And will only be re-run if one or more of the dependencies changed.

That's it!

Congratulations, you just learned how to use the very important useMemo React hook. 🥳🎉