ffxsam
ffxsam

Reputation: 27713

Does a container component re-rendering slow performance?

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

Answers (1)

Akshat Mahajan
Akshat Mahajan

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:

Image from the React docs explaining reconciliation

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 invoke shouldComponentUpdate 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

Related Questions