If you had enough of wandering on the internet searching for what the useMemo() hook in React does! Then you have come to the right post. I will give you a solid example based approach on when and why we use the useMemo() hook in certain situations.

You must already be familiar with the typical definition available on the internet

useMemo() allows you to memoize expensive functions so that you can avoid calling them on every render.

Many of you might be more confused now about what the term "memoized" means. If you search what memoize is, you will get a vague definition like "storing the results of expensive function calls and returning the cached result when the same inputs occur again". This is just a paraphrased version of what the definition for the useMemo() hook is. Don't worry, I was at the same place when I began learning hooks.

Now let's get an understanding of how and when we use the useMemo() hook by following an example. To begin with, initiate a react project with

npx create-react-app learning-usememo

The Noob Approach

Let us consider the following code now:

import React, { useState, useEffect } from "react";
import "./App.css";

function App() {
  const age = 20;
  const [name, setName] = useState("");
  const [dark, setDark] = useState(false);
  const user = { age, name };
  
  const buttonStyle = {
    backgroundColor: dark ? "#000" : "initial",
    color: dark ? "#FFF" : "initial",
  };

  useEffect(() => {
    console.log(user);
  }, [user]);

  return (
    <div>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button style={buttonStyle} onClick={() => setDark((currDark) => !currDark)}>
        Toggle Color
      </button>
    </div>
  );
}
export default App;
Noob code

This is the example we will follow. Our objective is to console log the user object every time there is a change in its values. I assume you know how useState and useEffect hooks work since they are more straightforward. The above example is pretty self-explanatory and understandable, hence I won't squander words explaining it.

The above code seems to do its job fine, except for the part that the user object is being console logged every time we toggle the colour of the button.

noob console logs

We don't need that, we only want to console log when the values of the user object change.

The reason the useEffect is triggering the console log is because a new user object is being created in every render with the above implementation.

The Advanced Approach

We can better the above implementation with some tweaks in the useEffect dependency array to get our desired outcome. Run the modified code below:

import React, { useState, useEffect, useMemo } from "react";
import "./App.css";

function App() {
  const age = 20;
  const [name, setName] = useState("");
  const [dark, setDark] = useState(false);
  const user = { age, name };

  const buttonStyle = {
    backgroundColor: dark ? "#000" : "initial",
    color: dark ? "#FFF" : "initial",
  };

  useEffect(() => {
    console.log(user);
  }, [name, age]);   👈

  return (
    <div>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button style={buttonStyle} onClick={() => setDark((currDark) => !currDark)}>
        Toggle Color
      </button>
    </div>
  );
}
export default App;
Advanced code

Now we have passed the "name" and "age" parameters directly to the useEffect dependency array. Now, the console log will only be triggered when these parameters change. No console log is working correctly. However, we have a new warning in the terminal.

Dependency error

We are using the "user" variable inside useEffect without passing it to the dependency variable.

Another flaw of this method is if we want to add new params to the user object, we will have to add it explicitly into the useEffect hook dependency array as well.

  .
  .
  .
  const age = 20;
  const birthday = "20-05-2001"  👈
  const [name, setName] = useState("");
  const [dark, setDark] = useState(false);
  const user = { age, name, birthday };  👈
  .
  .
  .
  useEffect(() => {
    console.log(user);
  }, [name, age, birthday]);  👈
  .
  .
  .
More parameters more dependencies 

The Pro Approach

Now let's see how the pros do it. Here is where the useMemo() hook comes in handy. Straight away, run the code below and get an understanding for yourself.

import React, { useState, useEffect, useMemo } from "react";
import "./App.css";

function App() {
  const age = 20;
  const [name, setName] = useState("");
  const [dark, setDark] = useState(false);
  const user = useMemo(() => {
    return { age, name };
  }, [name, age]);

  const buttonStyle = {
    backgroundColor: dark ? "#000" : "initial",
    color: dark ? "#FFF" : "initial",
  };

  useEffect(() => {
    console.log(user);
  }, [user]);

  return (
    <div>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button style={buttonStyle} onClick={() => setDark((currDark) => !currDark)}>
        Toggle Color
      </button>
    </div>
  );
}
export default App;
Pro code

Isn't it clean? Many of you might have already got an idea of what the useMemo() hook did here.

Let's go to the drawing board. Here is the syntax of the useMemo() hook.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo syntax

useMemo is similar to the useEffect hook as it only recomputes the value when there is a change in any of its dependencies. But unlike useEffect, the useMemo() hook can store the returned recomputed value directly to a variable.

In our example, useMemo simply recomputes the "user" object when there is a change in the parameters "age" and  "name". That is all useMemo is, recompute and store the result to a variable whenever there is a change in certain parameters. This enabled us to use the "user" object as a dependency for the useEffect hook which was console logging our "user" object. Now, everything falls into place and our objective has been accomplished.

Proper console logging

Conclusion

Even tho this article was a bit lengthy, reading this completely gave you the core ideology behind why and where we use the useMemo() hook. If I just showed you the implementation of the final version, you wouldn't understand why the concept of memoization and useMemo exist in the first place.

Thank you for reading. I will see you in another article, you can check my other articles here.