DEV Community

Szymon Sadowski
Szymon Sadowski

Posted on

How Memo changes rendering?

As developers, we strive to achieve the best performance in our applications. One way to do that in React is to restrict the number of re-renders. There are many tools that we are outfitted with to do that. In this short article, I will focus on the memoization of the component.

What triggers re-renders?

To better understand the subject, it is important to know how React triggers re-renders.

The component has three main reasons to render:

  • when the state changes,
  • when its parent renders (by default when the parent renders, all children also render),
  • when the context changes (if the component is subscribed).

Out-of-the-box modern declarative frameworks mostly re-render too much.

To block re-renders we can use memo (or pure components in-class component, but we won’t focus on that). Using memo causes that component to “remember” props and compare them with new ones. When we are dealing with primitive types the situation is simple and clear, when we are dealing with more complex types behavior may differ.

Fig. 1. Memo blocking render even though parent re-renders

Fig. 1. Memo blocking render even though parent re-renders

How to use Memo

Here we have our children component. It takes props checked and children. We export this component as memoized.

Fig. 2. Exporting component as memoized

Fig. 2. Exporting component as memoized

Now we will test it with different props and see when memo works and when it does not.

Text and boolean

First, we try sending as a boolean checked and text as children.

Fig. 3. Sending boolean and text to component

Fig. 3. Sending boolean and text to component

In this case, our memo won’t work and both parent and child will re-render every time we click on the checkbox. Why? Because the value of checked changes, and it influences the state of our MemoizedComponent.

What if we would get rid of this checked prop?

Text as children

Here we are only sending children, which is normal text.

Fig. 4. Sending only string as children

Fig. 4. Sending only string as children

Our memo will work just fine because the string is primitive, which React compares by value not reference. But this situation rarely happens. Most of the time we send JSX as children, so what will happen then?

JSX as children

Although, visual output will look exactly the same as in the previous case. Under the hood is happening something completely different and both child and parent will re-render every time we click the checkbox.

Fig. 5. Sending JSX as children

Fig. 5. Sending JSX as children

Why? Because every time when a parent is building its markup, this div is changed to React.CreateElement which is an object. Objects in JavaScript are compared by reference and that’s why a MemoizedComponent will always think that when parents re-renders prop changes even though nothing changes.

Summary

React Memo works, but only in specific circumstances. Most of the time in real-life applications it won’t help much. It can be used in components that have a lot of markup or are static like <Headers/>, <Footer/>, etc.

Your time will be better spent if you try to avoid prop drilling or go with hooks like useMemo or useCallback. But anyway always before you start optimizing your application try to profile it (using react devtools or similar). It’s important first to understand what is worth optimizing and spending your precious time on things that will improve performance.

Top comments (0)