What is PureComponent?

Tram Ho

Right from the start of language creation, React developers have the idea of ​​a child who has a pure, unbred, changed blood line => Pure component was born. This concept is called by many people with different names (stateful / pure, smart / dumb, container / presentational, etc.), but they all all describe the same meaning ” unchanged “. These components still use React.Component, but there has been an improvement to make it ” pure “.

In this article, I will discuss the concepts in which using Pure components is an advantage and when not to. We also discuss the difference between components and pure components

What problem does it solve?

By default, a simple React.Component has he shouldComponentUpdate always returns true. This is fine because that means React will always update the component in case there is any new data to display. However, it may lead to some unnecessary render cases. One of the most practical ways is to optimize what you shouldComponentUpdate lets him check whether he needs to render or not.

Other way  Developers React brothers have created a Pure component to prevent unnecessary rendering. Let’s look at the examples around this performance problem …

Example :

Note : bad code in the examples to show the problems we face. Please do not write them for actual projects

Todos

First, I have a React.component, this is what will be rendered. In this case, I have an array called todos , with each item has its title , done and notes properties.

Then there is another componentDidMount method. His purpose is to change the state of your app every second to see it 👀 How will React handle those changes. Right now, it will update state.todos to be the same as the previous state.todos value.

Finally, a render () function is also needed to make the example more meaningful. It will render a list containing the TodoItem components, and pass the title, done and notes properties. What you’re waiting for is waiting to see how these elements render.

TodoItem is similar to toos , but it is simpler, inheriting React.component but only implementing a render () function to display its props (title, done and notes).

What’s the problem?

Well, if you look at the console yourself, you’ll see the information displayed on it:

Every second, every second …

That sounds silly, my data has not changed !!!

You might be right – there, you don’t need to reder any of these elements because the data doesn’t change. But React doesn’t know this – the setState method from onComponentDidmount triggers re-rendering each time for the Todos component and its children.

How do we re-render less?

Now focus on TodoItem. It renders three times for each Todos render. So I’ll optimize it first then Todos.

How to restrict TodoItem rendering? 🛠

That leads me to pure love component. TodoItem does not need to be redrawn because no data has changed. The props that are passed each time are the same, there is no internal state. Try changing TodoItem to React.PureComponent

After changing …

Once TodoItems is initialized, they will never render again no matter how many times the parent Todos re-creates.

Boom. 💥

Have you grasped our problem yet? I just limited the unnecessary rendering of TodoItem by switching to using PureComponent

How does PureComponent work?

You already have a big clue in component usage. Pure component? How did it really work?

Do you know that we should often write shouldComponentUpdate to check if it is necessary to re-render the component? Well, React developers wrote us shouldComponentUpdate in PureComponent.

Note: React checks both props and state. Here I will focus on the state as it makes the examples of rendering easier to understand. But applying state to props here is similar.

Performs equality by iterating through keys on an object and returning false when any key has values ​​which are not strictly equal between the arguments. Returns true when the values ​​of all keys are strictly equal.

Wait, what does “strictly equal” mean? That’s a great question, so I’ll dedicate a whole lower part to it

Side note: shallow equality

A shallow equality is to check that the values ​​of the object ID (as in the memory address, where JS stores information for that particular object) are the same, but not the content of them is the same. So shallow equality means what you would think of the word “Equal”.

And an example of JS equal definition, maybe the definition of my JS vs them is different

Although we can clearly see that the content of array 2 is exactly the same as array 1 JS is registered, but with JS they are different because their id is different. In this case, I created two completely separate arrays, which happened to have the same data in it.

What instead?

We can check inside each index and see if all values ​​are the same – this is called a “deep” equality check . Something like this:

Why is a shallow equality so useful? Well, I can tell you it’s fast. In the above example we have to loop each item according to the index of the array to determine the equal array. But in another case, there’s something else in the array that could make your array browsing slow down quickly.

Pure Component is a shallow equality

React using shallow equality is a better performant way than doing deep equal. In fact, React doesn’t even provide a deep equality check. Instead you can perform a shallow check with the Pure component and write your own code check with shouldComponentUpdate or do nothing and it will automatically re-render the components (default which). Why is React not working closely with the deep equality check, try to imagine, with the case of many nested data, the test will take a lot of time and performance, it’s dangerous.

But life is not like a dream, it’s all a nice prospect being drawn in front of you with a friendly data guy. If the state and props change the component to render again when needed, yeah, your application is great. However, if you do not handle this data properly, it may lead to unintentional re-rendering when you need it …

I can give you an example: Let’s change TodoItem in the above example to a PureComponent, and change Todo’s componentDidMount to mess up some data.

If you run, the “done” state for the first item toggles every second. It also makes sense, I am updating the data and displaying it correctly. But try this:

Normally as we think, the first todo item will be re-created every second with “smelly” note. But that didn’t happen, Wth? In fact it only initial render and no “smelly” note.

Why is React not re-rendering the component?

Because I’m going to push “smelly” into the array rather than creating a new array . When React performed a shallow equality check for PureComponent TodoItem, it only checked oldState.notes === newState.notes , returning true even though the notes’ data was changed. To display this correctly, we need to rollback TodoItem to React.Component or forceUpdate to update the data changes.

Warning: Think of the child components

A common trap when switching from Component to PureComponent is that you forget that child components also need to be redrawn. With React, the parent’s not re-rendering results in its children being not updated either. So, if you use PureComponent with child components, it can be updated if the state and props compare differently via shallowly check => leading to its parent being updated as well.

You should only use PureComponent for parent components when you know which child must re-render when the parent does not re-render. I will add an example of this trap when changing from component to pure component

If you look at the code above, you can see that most of the code is the same. Here I changed Todos to a Pure Component and componentDidMount returned the original oldState object instead of creating a new object as above. Our wish is that the item flashes when the state is done on or off. But that again did not happen, when React performed a shallow equality check comparing oldState === newState , it found exactly the same object, even though its contents had changed. Todos lkhoong never re-render, and do not re-render TodoItem. We can do this easily by rolling back the Component

Summary

PureComponent is very powerful in that it can help you limit the number of unnecessary renderings that occur. However, it can also cause surprising problems. It is important to remember that PureComponent only tests shallow equality for props and state before making a decision whether or not to re-render. Leads to their children re-rendering or not. So use Pure Component whenever possible, it will help you to increase performance, but make sure that it will be re-painted as needed, and replace it as a component when needed.

Share the news now

Source : Viblo