React.memo helps you to avoid re-rendering of computationally heavy components
Tags: react, beginners, webdev, tutorial
Published: 2024-01-01 19:23:36

`React.memo` is useful when your component have some heavy computation or some expensive operations. It is similar to PureComponent but it works with functional components.

Let's say we have a component that renders a list of items. The list of items is passed as a prop to the component. The component renders the list of items as a list of `<li>` elements.

```jsx
// BookList.js
const BookList = ({ items }) => (
  <ul>
    {items.map((item) => (
      <li key={item.id}>{item.name}</li>
    ))}
  </ul>
)

export default List
```

Now, let's say we have a parent component that renders the `BookList` component. The parent component has a state that contains the list of items. The parent component renders the `BookList` component with the list of items from the state.

```jsx
// App.js
const App = () => {
  const [items, setItems] = useState([])

  useEffect(() => {
    fetch('/api/books')
      .then((res) => res.json())
      .then((data) => setItems(data))
  }, [])

  return <BookList items={items} />
}

export default App
```

Let's render the `BookItem` component for each item in the list. The `BookItem` component renders the details of the book. The `BookItem` component fetches the details of the book from the server when the component is mounted. The `BookItem` component renders the details of the book when the details are available.

```jsx
// BookList.js
const BookList = ({ items }) => (
  <ul>
    {items.map((item) => (
      <BookItem key={item.id} item={item} />
    ))}
  </ul>
)

// BookItem.js
const BookItem = ({ item }) => {
  const [details, setDetails] = useState(null)

  useEffect(() => {
    fetch(`/api/books/${item.id}`)
      .then((res) => res.json())
      .then((data) => setDetails(data))
  }, [item.id])

  // Compute the average rating of the book
  // TODO: This can be optimized with useMemo, I will cover that in next article separately
  const averageRating = details
    ? details.reviews.reduce((acc, review) => acc + review.rating, 0) /
      details.reviews.length
    : null

  return (
    <li>
      <h3>{item.name}</h3>
      <p>{item.author}</p>
      <p>Average Rating: {averageRating}</p>
    </li>
  )
}
```

Fetching the details of the book is an expensive operation. We don't want to fetch the details of the book when the list of items is changed. We only want to fetch the details of the book when the component is mounted. We can use `React.memo` to avoid re-rendering of the `BookItem` component when the list of items is changed.

```jsx
// BookList.js
const BookList = ({ items }) => (
  <ul>
    {items.map((item) => (
      <BookItem key={item.id} item={item} />
    ))}
  </ul>
)

// BookItem.js
const BookItem = ({ item }) => {
  const [details, setDetails] = useState(null)

  useEffect(() => {
    fetch(`/api/books/${item.id}`)
      .then((res) => res.json())
      .then((data) => setDetails(data))
  }, [item.id])

  // Compute the average rating of the book
  const averageRating = details
    ? details.reviews.reduce((acc, review) => acc + review.rating, 0) /
      details.reviews.length
    : null

  return (
    <li>
      <h3>{item.name}</h3>
      <p>{item.author}</p>
      <p>Average Rating: {averageRating}</p>
    </li>
  )
}

// Memoize the component to avoid re-rendering when the list of items is changed
export default React.memo(BookItem)
```

## What if only few items in the list is changed?

It will re-render only the items that are changed. It will not re-render the items that are not changed.

### When to use React.memo

- Real time apps that updates frequently. Example: Sports tracker app that renders the details of a match live. The details of the match are fetched from the server. The details of the match are updated every few seconds. You can memoize the component to avoid re-rendering of the component when the details of the match are updated. It helps to consume less CPU and memory.
- Apps that renders a list of items and updates it more frequently. Example: A chat app that renders the list of messages. The list of messages are updated frequently. You can memoize the component to avoid re-rendering of the component when the list of messages are updated.

### When not to use React.memo

- When the component is not expensive to render. Example: A component that renders a button. It is not expensive to render a button. You don't need to memoize the component. Pre-mature optimization is always evil 🤣
- When the component is expensive to render but the component is not re-rendered frequently. Example: A component that renders a list of items. The list of items are fetched from the server. The list of items are not updated frequently. You don't need to memoize the component.

Hope you learned something new today 🤓. Keep learning and share your comments by tagging me on twitter [@learnwithparam](https://twitter.com/learnwithparam) 🙌