memo vs useMemo in React
Tags: react, javascript, webdev, programming
Published: 2023-05-08 14:57:15

In this blog post, we will look at the `memo` and `useMemo` in React. We will do a deep dive into these performance optimization options offered by React and look at their difference and see in what cases `memo` and `useMemo` should be used.

**Dead Simple Chat** [**JavaScript Chat API and SDK**](https://deadsimplechat.com/javascript-chat-api-sdk) **allow you to add chat to your React application in minutes. Dead Simple Chat is a highly scaleable** [**Chat Platform**](https://deadsimplechat.com/) **that can be used for any chat use case.**

## What is `memo` in React?

`memo` is a [Higher Order Component](https://deadsimplechat.com/blog/higher-order-componets-in-react/) in React (If you want to learn about HOCs you can check out our detailed guide on [HOC in React](https://deadsimplechat.com/blog/higher-order-componets-in-react/)) that prevents the re-rendering of the component if its props are unchanged.

## What is `useMemo` in React?

`useMemo` is a React Hook, that caches the result of a computationally expensive function between re-renders and allows to trigger the method only when the method dependencies changes.

## React `memo` in Action

Let's look at an example under React `memo` and how we can use it to optimize our components.

```js
import { useEffect, useState } from "react";

const ChildComponent = () => {
  console.log("Child re-rendered");
  return <div>I am a Child Componenet.</div>;
};

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
    }, 1000);

    return () => {
      clearInterval(interval);
    };
  }, []);

  return (
    <div className="App">
      Count: {count}
      <ChildComponent />
    </div>
  );
}
```

If you look at the example above, we have created a parent component called as `App` component.

In the `App` component we are running a `setInterval` and increment the `count` value by 1 every second.

If we run this code, you will see "Child re-rendered" continuously printed on the console.

It is because each time the `count` is updated, the `App` component is redrawn, thus all the child components are also re-drawn.

To prevent this we can use the `memo` HOC to create a *memoized* version of our `ChildComponent`. As our `ChildComponents` do not accept any props it is will not be redrawn each time the `App` component is updated.

[click here for example video](https://deadsimplechat.com/blog/memo-vs-usememo-in-react/#react-usememo-in-action)

Here is the *memoized* version of our using React Memo:

```js
import { memo, useEffect, useState } from "react";

const ChildComponent = () => {
  console.log("Child re-rendered");
  return <div>I am a Child Component.</div>;
};

const MemoizedChild = memo(ChildComponent);

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
    }, 1000);

    return () => {
      clearInterval(interval);
    };
  }, []);

  return (
    <div className="App">
      Count: {count}
      <MemoizedChild />
    </div>
  );
}
```

[click here for example video](https://deadsimplechat.com/blog/memo-vs-usememo-in-react/#react-usememo-in-action)

When you will run this code, you can see "Child re-rendered" is printed only twice, and not every time the `App` component is updated.

But as you have noticed it is printed twice and not once, because `memo` is performance optimization and not a guarantee.

React will still re-render the *memoized* version of the component as it sees fit at regular intervals.

**Dead Simple Chat's** [**JavaScript Chat API and SDK**](https://deadsimplechat.com/) **allow you to easily add custom chat to your React Application.**

## React `useMemo` in Action

The `useMemo` hook is used to optimize the computationally expensive function, that you don't want to call unless the input to the function changes.

*Do not use the* `useMemo` hook to call async requests, for that you should use the `useEffect` hook.

Now let's look at an example of `useMemo` to better understand its working.

In the example below we have React component called as `BlogWriter`. The `BlogWriter` component allows the user enter a title of the blog post, and post body.

It then `calculateTextStats` method to compute the word count of the blog post **body.**

```js
import React, { useState } from "react";

const calculateTextStats = (text) => {
  console.log("calculateTextStats called");

  const words = text.trim().length > 0 ? text.trim().split(/\s+/) : [];
  const characters = text.replace(/\s+/g, "").length;

  return {
    wordCount: words.length,
    characterCount: characters,
  };
};

const BlogWriter = () => {
  const [body, setBody] = useState("");
  const [title, setTitle] = useState("");
  const stats = calculateTextStats(body);

  return (
    <div>
      <input
        style={{ marginBottom: "10px" }}
        type="text"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        placeholder="Post title"
      />
      <br />
      <textarea
        value={body}
        onChange={(e) => setBody(e.target.value)}
        placeholder="Post Body"
      />
      <div>
        <p>Word count: {stats.wordCount}</p>
        <p>Character count: {stats.characterCount}</p>
      </div>
    </div>
  );
};

const App = () => {
  return (
    <div style={{ margin: "20px" }}>
      <h1>Create Post</h1>
      <BlogWriter />
    </div>
  );
};

export default App;
```

We have added a `console.log("calculateTextStats called");` statement in the `calculateTextStats` method to print on the console each time the method is called.

When you will run this application, you will notice the "**calculateTextStats called"** will be printed on the console.

We can optimize this function using the `useMemo` hook. By using the `useMemo` hook we make sure that the `calculateTextStats` function is only called when the "Post Body" is updated.

To update our example to use the `useMemo` hook for optimization we just need to replace the code:

```js
const stats = calculateTextStats(body);
```

with

```js
  const stats = useMemo(() => {
    return calculateTextStats(body);
  }, [body]);
```

Here is the complete code example for reference:

```js
import React, { useMemo, useState } from "react";

const calculateTextStats = (text) => {
  console.log("calculateTextStats called");

  const words = text.trim().length > 0 ? text.trim().split(/\s+/) : [];
  const characters = text.replace(/\s+/g, "").length;

  return {
    wordCount: words.length,
    characterCount: characters,
  };
};

const BlogWriter = () => {
  const [body, setBody] = useState("");
  const [title, setTitle] = useState("");

  const stats = useMemo(() => {
    return calculateTextStats(body);
  }, [body]);

  return (
    <div>
      <input
        style={{ marginBottom: "10px" }}
        type="text"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        placeholder="Post title"
      />
      <br />
      <textarea
        value={body}
        onChange={(e) => setBody(e.target.value)}
        placeholder="Post Body"
      />
      <div>
        <p>Word count: {stats.wordCount}</p>
        <p>Character count: {stats.characterCount}</p>
      </div>
    </div>
  );
};

const App = () => {
  return (
    <div style={{ margin: "20px" }}>
      <h1>Create Post</h1>
      <BlogWriter />
    </div>
  );
};

export default App;
```

As you can see in the demo now when we update the "Post title" now the "calculateTextStats called" message is not printed on the screen.

Only when we update the "Post Body" we can see the "calculateTextStats called" message being printed on the screen.

## Difference between `memo` and `useMemo`

As we have seen with the above examples `memo` and `useMemo` have similar names, and different approaches, but both are used to optimize the React components.

The `memo`  is a higher-order component which is used to create an optimized version of a component that is re-rendered only when props change.

Whereas `useMemo` is a hook which is used to cache the result of an expensive function inside a component, and only calls the expensive function when its dependencies change.

To summarize the difference, the `useMemo` is used to optimize the computationally expensive operations that run inside the component, whereas `memo` is used to optimize the rendering of the component itself.

## When `useMemo` should be used?

If your code runs fine without using `useMemo` then leave it as is. It is not a good idea to be premature optimizations.

But if you notice hangs or lags in your application. If you notice the UI becomes unresponsive then you can investigate the computationally expensive methods in your application, and optimize them using `useMemo`.

Here are some of the common scenarios that you can look for in your application to optimize using `useMemo`

### Cache the Result of Computationally Expensive Method

You can cache the result of a computationally expensive method so that other UI interactions do not result in the execution of the method.

Check out the example below:

```js
import React, { useState, useMemo } from "react";

const doLargeCalculation = (num) => {
  let result = num;
  for (let i = 0; i < 100000000; i++) {
    result += Math.random();
  }
  return result.toFixed(2);
};

const LargeCalculationComponent = () => {
  const [input, setInput] = useState(0);
  const result = useMemo(() => doLargeCalculation(input), [input]);

  return (
    <div>
      <input placeholder="Do nothing.." type="text" />
      <br />

      <input
        type="number"
        value={input}
        onChange={(e) => setInput(+e.target.value)}
      />
      <p>Result: {result}</p>
    </div>
  );
};

const App = () => {
  return (
    <div style={{ margin: "20px" }}>
      <LargeCalculationComponent />
    </div>
  );
};

export default App;
```

Check the example above, here updating the text box with place holder will not result in the execution of the **doLargeCalculation** method.

![](https://deadsimplechat.com/blog/content/images/2023/04/Screenshot-2023-04-18-at-12.39.28-PM.png align="left")

### Caching the Derived State

If we want to cache the value computed using the derived state we can use the `useMemo` hook to prevent unnecessary calculations.

```js
import React, { useState, useMemo } from "react";

const calculateTotal = (numbers) => {
  return numbers.reduce((acc, val) => acc + val, 0);
};

const AdderComponent = () => {
  const [numbers, setNumbers] = useState([]);
  const [input, setInput] = useState("");

  const total = useMemo(() => calculateTotal(numbers), [numbers]);

  const add = () => {
    setNumbers([...numbers, Number(input)]);
    setInput("");
  };

  return (
    <div>
      <input
        type="number"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Input a number"
      />
      <button onClick={add}>Add</button>
      <p>Tape: {numbers.join(", ")}</p>
      <p>Total: {total}</p>
    </div>
  );
};

const App = () => {
  return (
    <div style={{ margin: "20px" }}>
      <AdderComponent />
    </div>
  );
};

export default App;
```

In the above code the `AdderComponent` acts like a tape calculator,  it pushed the new numbers into an array and then displays the total.

By using the `useMemo` hook on the `total` we ensure that the total calculation is only performed when the numbers array changes.

This prevents unnecessary recalculation of the total  when the component re-renders for any reason.

![](https://deadsimplechat.com/blog/content/images/2023/04/image-6.png align="left")

## `useMemo` common pitfalls

`useMemo` is a powerful optimization tool, but you should be aware of some of the most common pitfalls when using `useMemo` in your applications:

* **Pre-mature Optimisation:** Using `useMemo` in your application, when it is not needed, is the most common pitfall. This introduces unnecessary complexity in the code and might introduce some unintended behaviour in the application and hard-to-find bugs.
    
* **Using** `useMemo` **on dependencies that change a lot**: There is no benefit of using `useMemo` on dependencies that change a lot. Even with using `useMemo` if the dependencies change the recalculations would be performed. In these cases, you should not use `useMemo` as it does not result in any performance benefit.
    
* **Using** `useMemo` **to handle side-effects**:  Data fetching for storage or API, sending Ajax requests, and manually updating the DOM are all examples of side-effects, all these operations should be performed in the `useEffect` hook. The `useMemo` should only be used for synchronous operations, asynchronous operations should be handled in `useEffect` hook and combination with `useState`.
    

## When `memo` should be used?

React `memo` should be used in cases where the component is re-render too often even though its props are unchanged.

### Reducing unnecessary render when Parent Component update

In a scenario where the parent component updates but the props of the child component are unchanged.

In this case, if we wrap the child component in `memo` then it would prevent the re-rendering of the child component unless the props of the child component also change.

We have seen an example of this in this blog post, but here is another example:

```js
import React, { useState, memo } from "react";

const ChildComponent = memo((props) => {
  console.log("Rending Child Component");
  return <div>Counter: {props.count}</div>;
});

const ParentComponent = () => {
  const [count, setCount] = useState(0);
  const [toggle, setToggle] = useState(false);

  return (
    <div>
      <button onClick={() => setCount((prevCount) => prevCount + 1)}>
        Increment
      </button>

      <button onClick={() => setCount((prevCount) => prevCount - 1)}>
        Decrement
      </button>

      <button
        style={{ fontSize: toggle ? "40px" : "12px" }}
        onClick={() => setToggle((prevToggle) => !prevToggle)}
      >
        Toggle
      </button>
      <ChildComponent count={count} />
    </div>
  );
};

const App = () => {
  return (
    <div style={{ margin: "20px" }}>
      <ParentComponent />
    </div>
  );
};

export default App;
```

In the above code, there are two state variables in the parent component, one is `count` and another one is `toggle`.

`count` is passed as a prop to the child component, and we have memoized the child component, so it will only be re-rendered when its prop that is count changes.

The `ChildComponent` will not be re-rendered when the `toggle` state is updated.

### Caching Lists

React `memo` can be used to cache the list items, when a list is frequently updated.

By using `memo` on the List Items you ensure that the entire list is not re-rendered when an item in the list is updated.

Let's look at an example:

```js
import React, { useState, memo } from "react";

const TodoItem = memo(({ item }) => {
  console.log(`Rendering todo item: ${item}`);
  return <li>{item}</li>;
});

const TodoListComponent = () => {
  const [todos, setTodos] = useState(["Buy milk", "Buy eggs", "Drink milk"]);
  const [newTodo, setNewTodo] = useState("");

  const addTodo = () => {
    setTodos([...todos, newTodo]);
    setNewTodo("");
  };

  return (
    <div>
      <input
        type="text"
        value={newTodo}
        onChange={(e) => setNewTodo(e.target.value)}
      />
      <button onClick={addTodo}>Add Todo</button>
      <ul>
        {todos.map((item) => (
          <TodoItem key={item} item={item} />
        ))}
      </ul>
    </div>
  );
};

const App = () => {
  return (
    <div style={{ margin: "20px" }}>
      <TodoListComponent />
    </div>
  );
};

export default App;
```

In this example the `TodoListComponent` manages a list of todos. Each time todo is added a new `TodoItem` component is rendered on the screen.

By wrapping `useMemo` around the `TodoItem` component, when a new Todo is added to the the `todos` array, all the `TodoItems` are not re-drawn.

It is especially useful in cases where a large list of todo has to be drawn on the screen. Wrapping each individual item in `memo` we ensure only the Item that is being updated is redrawn.

In the above video, as I added "Eat Eggs"  only the "Eat Eggs" todo was rendered and not the entire list.

## `memo` common Pitfalls

A common pitfall to keep in mind when using React `memo` is that it does shallow prop-checking, and if your props are functions, array or object the component will re-render each time the parent component renders.

To prevent this you can pass a comparison function the `memo` HOC. You can find more details about this at the official React Documentation: [Specifying a custom comparison function](https://react.dev/reference/react/memo#specifying-a-custom-comparison-function)

**Keep in mind if are passing the comparison function then you must compare every prop, including functions.**

## Conclusion

In this blog post, we have seen what is React `memo` and `useMemo`. What are the differences between the two, and how we can use them to make our React applications more performant.

We have seen several code examples, and scenarios where to apply `memo` and `useMemo` and also some of the common pitfalls.

This article was originally published on the deadsimplechat website:[ memo vs useMemo in React](https://deadsimplechat.com/blog/memo-vs-usememo-in-react)