React useMemo() hook explained

The useMemo() hook is one of many built-in React hooks that you can use inside your function components.

This hook is designed to improve the performance of your React component through the use of memoization technique (you can also say memorizing, but the right technical term is memoizing)

Memoization is an optimization technique where the result of an expensive function call is stored in memory. The computer did this by “remembering” the input that it received, connecting the input with the result.

For example, let’s say you have a function add() that adds up two numbers passed as its arguments:

const num = add(1, 1);
// num = 2

Using the memoization technique, you can memoize the result of calling the add() function. The next time the function is called, the computer would first look at the arguments you passed to the function.

When the computer sees that you are passing the same arguments as the previous call – which is (1, 1) in the case above – then it will return the value 2 stored in the memory and skips running the function.

The useMemo() hook is used to apply the memoization technique to the function that you passed as its argument.

Using the add() function as an example, the hook syntax is as follows:

const firstNumber = 1;
const secondNumber = 1;

const num = useMemo(() => {
  add(firstNumber, secondNumber);
}, [firstNumber, secondNumber]);

In the above example, the useMemo() hook accepts two arguments:

  • The first is a callback function that will run the function to be memoized
  • The second is a dependency array that will be observed by the hook

As long as the values inside the dependency array don’t change, then the memoized function add() won’t be called and the memoized result will be returned by the hook.

To test a memoized function, you can add a console.log() statement inside it. When the value is retrieved from memory, the log won’t be printed.

In the following <App> component, the expensive() function is called every time you clicked on the <button> even though the props are the same:

function App() {
  const [toogle, setToogle] = useState(false);

  return (
    <>
      <ChildComponent num={1} />
      <button onClick={() => setToogle(!toogle)}>{toogle.toString()}</button>
    </>
  );
}

function ChildComponent(props) {
  const { num } = props;
  const expensive = () => {
    console.log("running expensive function!");
    return num + num;
  };
  return <h1>{expensive()}</h1>;
}

Using the useMemo() hook, you can skip the expensive() function call as in the example below:

function ChildComponent(props) {
  const { num } = props;

  const expensive = (num) => {
    console.log("running expensive function!");
    return num + num;
  };

  const result = useMemo(() => expensive(num), [num]);
  return <h1>{result}</h1>;
}

The <ChildComponent> above will only call the expensive() function once during the initial render and will return the value stored in memory for subsequent calls.

The dependencies of the useMemo() hook usually comes from props passed by the parent component, which means as long as the props passed to the component remains the same, the memoized function will be skipped.

When should you use useMemo() hook?

Since the useMemo() hook is designed for optimization, you need to make sure that you are only applying the hook when you have expensive function calls inside your project.

Memoization should only be used when you have a component with an expensive function call that could re-render when the parent component has its props changed.

One example where useMemo() hook might be useful is when you have a social media application with switchable light or dark themes and an expensive search function call.

The code pattern would look like the example below:

function App() {
  const [theme, setTheme] = useState("light");
  const [username, setUsername] = useState("");

  const changeTheme = () => {
    const newTheme = theme === "light" ? "dark" : "light";
    setTheme(newTheme);
  };

  return (
    <>
      <input
        type="text"
        placeholder="Search Users"
        onChange={(e) => setUsername(e.target.value)}
      />
      <SearchResult username={username} />
      <button onClick={() => changeTheme}>{theme}</button>
    </>
  );
}

function SearchResult({username}) {
  const expensiveSearch = (username) => {
    // perform search and return results
  }

  return <h1>Search result placeholder</h1>
}

You can memoize the result of that expensiveSearch() call using the useMemo() hook so that if the user changes the theme after performing a search, the same search result is displayed from memory instead of calling the search function again.

And that will be all about the useMemo() hook 😉

Take your skills to the next level ⚡️

I'm sending out an occasional email with the latest tutorials on programming, web development, and statistics. Drop your email in the box below and I'll send new stuff straight into your inbox!

No spam. Unsubscribe anytime.