React | Component Performance Comparison
React version 16.6 has introduced Memoized components. A functional component without the baggage of state and component lifecycle methods. The purpose is to maximize performance. I wanted to put that to the test and see how it compares to other React component types.
To answer that question I’ve built a simple React app which runs a user-selected number of operations and plots the results on a line graph. If you’re not in the mood to read this skip to the bottom and play around with the app.
There are four fundamental component types in React:
- Class Component
- Pure Component
- Functional Component
- Memoized Component
Class components are the most common type and the original component architecture. If you’re starting out with React this is where you’ll begin. They come coupled with the ability to store state as well as implement component lifecycle methods.
Pure Components are almost identical to Class components. The one difference is that they don’t have the
shouldComponentUpdate lifecycle method. The reason for this is that Pure components, by default, come coupled with their own implementation of
shouldComponentUpdate. They perform a shallow comparison of changes to
state. If there are no changes then React avoids a re-render thus increasing performance.
Memoized components can be thought of as a combination of a Pure Component and a Functional component. In fact, some people wanted them to be called Pure Functional components. Dan Abramov shot this down for valid reasons but nonetheless it helps with an understanding of what they do. Memoized components are Functional components that do a shallow comparison of changes to state and prop to prevent unnecessary re-rendering. Because of these features they have the potential to be the best performing component type of all.
I wanted to put Memoized components to the test. That’s why I built this simple app to compare all types. I’ve constructed the app such that the user enters the amount of operations to be performed on each component. Each operation is a re-render with the a text output of the component type and the incrementing operation number.
Each time a render is complete the time it took to complete the operation is pushed into an array. Only one component type is processed at a time so that they can each be tracked in isolation. After all tests are completed the results of Time (ms) vs. Operations is plotted together with a summary table.
The results above show Memoized components performing slightly better than the other types over 2000 operations. After multiple implementations I’ve noticed that the results deviate slightly with the common trend of them performing with similar computation time. I know that this is a somewhat contrived example. The differences in component types only really become pronounced as the components become much heavier. Nonetheless, I thought this would be an interesting experiment to run.
Please play around with the app and add your comments and ideas about how I can improve this experiment. I’ll be happy to implement any good ideas. If you’d like to have a look at the code open up the editor in Code Sandbox. All code is written in the
index.js file. As always, happy coding!