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
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
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
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
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
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)