How to improve performance using memoization in React? [pt.1]

Ingryd Moura
hurb.labs
Published in
6 min readJun 3, 2022

In this first part, I’ll talk about when and how to use memo to improve performance in your React application. In the other parts, I will talk about how to use and what the useMemo and useCallback are for.

React.memo() image

This article is divided as follows:

  • Diffing Algorithm
  • Profiler
  • memo

I know you must be saying to yourself:
- “If I use all of them in my application, it would be wonderful!”

Me:

Crying baby giphy

Just stop thinking about this, please! Let’s take it easy! 🙌

First, let’s understand what’s is the React Diffing Algorithm.

Diffing Algorithm

It is the component rendering process! This process compares the new HTML with the older HTML if it exists.

This process has a few steps:

  • The component creates its HTML;
  • Check if there is a change in the HTML created to this previous HTML (only if it’s not the first time it’s being rendered);
  • Perform the diffing algorithm to apply those changes.

For example, when a component has any changes, such as a state changed or made a change in a child component, this component re-renders; that is, the entire DOM has generated again, but this is not done directly in the HTML that we users see but in the VirtualDOM.

❗️An important information: React doesn’t remove all content because of one change; it just replaces what was changed.

<Container className="container" title="Container1">Container1</Container><Container className="wrapper" title="Container1">Container1</Container>

In the example above, React doesn’t remove Container, title, or your children, it just replaces the className.

Profiler

So, before we get to the most important matter, I need to explain React Developer Tools, a browser extension that you need to install to make it work. Then, we’ll use the Profiler to find out how the memo works in your application.

And here is the Profiler! 🎉

Profiler home screen image

The Profiler works by recording specific actions. You can do this by clicking the circle button shown in the picture below:

Image of the mouse cursor on “start profiling”

And it has two types of visualization:

  • Flamegraph chart: Sort by rendering order. Each bar in the graph represents a React component, and the width of each bar represents how long it took to render the component and its children.
Flamegraph chart image
  • Ranked chart: Sort by render time. Displays each component in the commit as a bar, but this time they are ordered by the duration of their render.
Ranked chart image

And these colored rectangles represent each rendering that took place in the application. We’ll see more about this later!

Image of colored rectangles representing each render

There are more details about Profiler, but I don’t want to make this article tooooo boring, so I’ll explain a few things along this journey.

No more blah blah blah!

Blah blah blah image

Finally…

Memo

React.memo is a HOC (Higher-Order Component).

“Wait…What?!”
A higher-order component is a function that receives a component and returns a new component.

“So…How does memo help us?”

It prevents all child components from rendering because of the parent render.

“I still don’t understand… what do you mean?”

For example, a simple application renders a fruit in the list by clicking the “Add” button:

And this is a Fruit component:

In Profiler do as follows: “Start profiling” -> Add fruits in your application -> “Stop profiling”

So…you see this:

Image with App and Fruit components rendered

Note that the Fruit components are colored, which means, they have been rendered. They were rendered because the App component was rendered.

The memo will help us solve this problem! 🙏

The memo will say the following to that component “Heeey, when your parent component renders BEFORE entering the render flow, I want you to compare the properties of that component, and if no information has changed, I want you to not even enter that render flow.”

Let’s go add a memo in the Fruit component:

Now, if you test this in your Profiler again…

Giphy of surprised cat
Image with Fruit 0 component not rendered

Note that the “Fruit 0" component didn’t render!

The colored Fruit component, on the other hand, has been rendered because this second commit is the first time it has been rendered.

Let’s check how it goes when we add 3 fruits:

Image with Fruit 0 and Fruit 1 components not rendered

In this case, It’s added the “Fruit 0” (gray), “Fruit 1” (gray), and “Fruit 2” (green). “Fruit 0” and “Fruit 1" was added in the first and second render. The third and last commit is colored because it was the first time that “Fruit 2” was rendered.

React.memo also accepts an optional second parameter to create a custom comparison.

For example:

propsAreEqual() function returns true if prev and next props are equal.

The same assertion was made at the beginning:

“I’ll use it on everything then!😍”

NO NO NO NO NOOOO!

“NOOOO!” giphy

The memo works like this:

It needs to compare! It needs to go through the properties of the component and compare whether they are the same as before, and then allow it to enter or not the render flow.

Suppose the memo has properties to compare. In that case, this may be slower than creating a new version of this component and letting React’s reconciliation algorithm do what it already does in some cases.

So it’s not worth using memo on all components because this property calculation can be slower than letting the React reconciliation algorithm run.

So...when should I use it?

  • Medium to large components: this example I used is quite simple, but in the case of an application with a much larger component, with a lot of functionality and which shows a lot of things on the screen it would be good to use memo.
  • Re-renders with the same props: when a component renders several times and always with the same properties.
  • Complex Pure Functional Components: this means that given the properties that I pass to the component, the return will always be the same. It’s not a pure component if you use external resources of this component to make it work; for example, a component that makes a comparison with some date gets the current date and makes a countdown. This current date is happening in the users' environment; it is not something that comes from the properties.

This is the first part of the article; I hope I helped you with the questions: what is, how, and when to use memo.

In the following articles, I will talk about useMemo and useCallback, showing examples and how to use them.

Giphy of a waving cat

See you later!

--

--