Reputation: 27713
Let's say I have the following:
class ThingContainer extends React.Component {
// ...
render() {
return <Thing { ...someProps } />
}
}
And let's say ThingContainer
re-renders 50 times, but if Thing
has a very extensive shouldComponentUpdate
method that restricts it to re-rendering only twice, am I ok performance-wise?
In other words, if a component C1 re-renders 50 times but returns only a component C2 that renders once or twice (C2 being very complex layout-wise), does this have almost no performance impact since C2 is not re-rendering?
Upvotes: 1
Views: 359
Reputation: 9846
Obviously the only way to really answer this is to profile your rendering time.
But here's the breakdown: rendering times with React are always going to be very, very fast for virtually any operation you can perform. This is because they manipulate a virtual DOM, rather than the actual DOM (which is much more expensive), and are heavily optimized to force component re-rendering only when they have to (usually only when state or props change - and only the changed element and its children are affected).
Unless you have definitive proof that re-rendering is a major bottleneck, it isn't worth trying to eke out ever last iota of performance. I recall building a single-page React application which would re-render the entire page on every meaningful interaction - this was a fairly complex 300-line React application - and each re-rendering took only 50 ms. For comparison, that was a tenth of the time (500 ms) my AJAX requests took to complete. My network latency dominated my rendering times to the point that it wasn't worth bothering to touch the rendering code.
If shouldComponentUpdate
is set in your component C2
to only render one or twice, then it will not be touched by React at all unless C2
specifies a render is required. Only C1
will be re-rendered - its children and grandchildren will not be affected. This is explained in the diagram below:
In the diagram, component C1
needed re-rendering but C2
was set to return false
for shouldComponentUpdate
. C2
and all of its children are left untouched by React. This is a near perfect analogy to your case, and the same results apply. You can read more about this in the docs:
Here's a subtree of components (see image). For each one is indicated what
shouldComponentUpdate
returned and whether or not the virtual DOMs were equivalent. Finally, the circle's color indicates whether the component had to be reconciled or not.In the example above, since
shouldComponentUpdate
returned false for the subtree rooted at C2, React had no need to generate the new virtual DOM, and therefore, it neither needed to reconcile the DOM. Note that React didn't even have to invokeshouldComponentUpdate
on C4 and C5.For C1 and C3
shouldComponentUpdate
returned true, so React had to go down to the leaves and check them. For C6 it returned true; since the virtual DOMs weren't equivalent it had to reconcile the DOM. The last interesting case is C8. For this node React had to compute the virtual DOM, but since it was equal to the old one, it didn't have to reconcile it's DOM.Note that React only had to do DOM mutations for C6, which was inevitable. For C8, it bailed out by comparing the virtual DOMs, and for C2's subtree and C7, it didn't even have to compute the virtual DOM as we bailed out on
shouldComponentUpdate
.
Upvotes: 1