Chapter 8. Performance of React Apps
In the previous chapter, we learned to use various React add-ons. We saw add-ons ranging from immutability helpers to test utilities.
In this chapter, we will look at React performance tools that can improve the performance of our React apps. In particular, we will be using the PERF add-on, PureRenderMixin
and shouldComponentUpdate
. We will also look at some of the gotchas that needs to be considered while using the performance tools provided by React.
Performance of React apps
"Hey Mike, I have few questions for you today. I have been thinking about our search app over the weekend. Do you have some time to discuss them?" Shawn asked.
"Sure, but let me get some coffee first. Okay, I am ready now. Shoot!" said Mike.
"I have few questions about the performance of React apps. I know React is very good at re-rendering the component tree whenever the state changes. React has made it very easy for me to understand and reason my code. However, does it not hamper the performance? Re-rendering seems like a very costly affair, especially when re-rendering large component trees." Shawn asked.
"Shawn, the re-rendering can be expensive. Nevertheless, React is smart about it. It only renders the part that is changed. It does not need to re-render everything on the page. It's also smart at keeping the DOM manipulation as least as possible."
"How is that possible? How does it know which part of the page is changed? Does it not depend on user interactions...
"Shawn, React uses virtual DOM to keep track of what has changed in the real DOM. It's concept is very easy to understand. React always keeps a copy of the representation of the actual DOM in memory. Whenever something changes, such as some state manipulation, it calculates another copy of the DOM that will be generated with new state and props. Then it calculates the difference between the original copy of the virtual DOM and the new copy of the virtual DOM. This difference results in minimal operations on the real DOM that can take the current DOM to a new stage. In this way, React does not have to do major changes when something changes." Mike explained.
"But isn't the diff calculation expensive?" asked Shawn.
"It's not expensive when you compare it with actual DOM operations. Manipulation of DOM is always expensive. The comparison of virtual DOM occurs in JavaScript code, so it is always faster than doing manual DOM operations." said Mike.
"Another advantage of this approach...
"Let's start with installing the PERF addon."
"We need this add-on only in the development mode. This is an important point to remember because in production, we don't need the debugging information as it may make our app slow." informed Mike.
"Shawn, the PERF add-on can be used to see what changes React is doing with the DOM, where is it spending time while rendering our app, is it wasting some time while rendering, and so on. This information can then be used to improve the performance of the app." said Mike.
"Let's start by exposing the PERF add-on as a global object. We can use it in the browser console while our app is running to see how React is making changes as per the user interactions." explained Mike.
DOM operations performed by React
"Shawn, the PERF add-on can show us which DOM operations were performed by React. Let's see what manipulations React did to the DOM to render the list of books by Dan Brown." said Mike.
"The Perf.printDOM()
method tells us the DOM manipulations made by React. It has made only two set innerHTML
calls. First one is to render the spinner and second one is to render the list of rows. In between, we see a call to remove, which must be when the spinner was removed from the page."
"Wow, this method looks very handy as it can tell us if React is somehow doing some extra DOM manipulations." said Shawn.
"Yes, but there are more tools for the purpose analyzing the performance. Let's see how much time does React require to render each component. This can be achieved using Perf.printInclusive()
." explained Mike.
Time taken to render all the components
"This method prints the overall time taken to render all the components. This also included the time required to process props...
"Shawn, PureRenderMixin
is an add-on that can be used in place of shouldComponentUpdate
. Under the hood, it uses shouldComponentUpdate
and compares the current props and state with the next props and states. Let's try it in our code. First, we need to install the add-on, of course." said Mike.
"Shawn, let's see the wasted time now that we have used PureRenderMixin
." said Mike.
"Oh, it got worse. The PureRenderMixin
function added the time wasted in re-rendering Form
and Header
components back. What is going on, Mike?" Shawn asked.
"Calm down! I am going...
"Mike, I have a question though. All said and done, why does PureRenderMixin
perform shallow comparison in the first place? Should it not perform a deep comparison so that we will always have better performance?" Shawn was not very happy with PureRenderMixin
.
"Well, there is a reason for this. Shallow comparison is very cheap. It does not take much time. Deep comparison is always expensive. Therefore, PureRenderMixin
does shallow comparison, which is good enough for most of the simple use cases," said Mike.
"However, React does provide us an option of defining our own version of shouldComponentUpdate
as we saw earlier. We can completely short-circuit the re-rendering process by just returning false
from shouldComponentUpdate
or we can compare only those props that are required by our component."
"True, just like we had written shouldComponentUpdate
for the BookRow
component right?" asked Shawn.
In this chapter, you learned about the performance tools provided by React and how to use them. We used the PERF add-on: shouldComponentUpdate
and PureRenderMixin
. We also saw which areas to look for when trying to improve the performance of our apps. We also studied the pitfalls while improving the performance, especially with PureRenderMixin
. In the end, we discussed the importance and advantages of immutable data.
In the next chapter, we will look at the data model of React in detail using React Router and Flux. You will learn how to use React with other frameworks such as Backbone.