In the frontend development community, we tend to use the word performance
quite a lot. We all have the common goal of having a performant application. Brian Vaughan developed react-window
with this in mind and he did a great job of giving us a powerful tool to achieve this goal.
react-window
in theory is very simple to understand, the window refers to the view the user can see.
react-window
will only render what the user can see, because why would we bother using resources rendering areas that the user can’t see? That would just be pure silliness!
Well wouldn’t it be very hard to profile an application, without an actual application? I have created an application that fetches a large list of movies, you can check out the repo here.
Just run an npm install
and then npm start
, you should now see the following on localhost:3000
The following code in movie-list.js
will get5000
movies from our large response:
const moviesList = movies.slice(0, 5000);
We’ll use 5000
as our sample size as it’s quite chunky and will take some time to render.
We’ll start by measuring our initial performance, the first thing we’ll measure is our frame per second (FPS
). To enable this in Chrome DevTools, you need to turn on rendering by clicking more tools then rendering.
Our Frame Rate
is at 34.0 fps
which is quite slow, we are more looking for achieving something around 60fps
.
The next thing we’ll measure is our First Meaningful Paint
. To do this I ran a Lighthouse report, this couldn’t handle the 5000
movies so just for this test I moved the number of movies to 500
As you can see from the above, the performance is not good and remember this is with 500
movies, not 5000
.
I will be making all the performance upgrades on a new branch called performance-increased
, this means when you clone the repo you will have the slow application on the master
branch and you can toggle between both to see the difference.
To implement react-window
, you first need to install it by running npm install react-window
, then import FixedSizeList
.
import { FixedSizeList as List } from 'react-window';
To work with the List
component, we need to create a Row
component like so:
// all props are passed by the List component
const Row = ({ index, style, data }) => {
const movie = data[index];
// style is passed by the List component to give our Row the correct dimensions
return (
<div style={style} key={index}>
<Movie key={index} {...movie} />
</div>
);
};
We won’t go into the Movie
component as it doesn’t matter, basically it’s our view for each movie.
With our Row
component created, we can then implement our List
component which we wrap in an AutoSizer
component:
<AutoSizer>
{({ height, width }) => (
<List
className="List"
height={height}
itemCount={1000}
itemSize={150}
width={width}
itemData={moviesList}
>
{Row}
</List>
)}
</AutoSizer>
The AutoSizer
component will automatically scale our Row
component’s dimensions to it’s container by passing a height
and width
to our List
component. You can also just pass static values to the height
and width
prop.
To install AutoSizer
, run npm install react-virtualized-auto-sizer
then to import:
import AutoSizer from 'react-virtualized-auto-sizer';
The List
component is quite simple, as you can see we have a prop called itemData
which we pass all of our 5000
movies This allows us to access an individual movie in our Row
component.
const movie = data[index];
The itemSize
prop is the height of each row. The rest of the props are quite simple.
The List component passes a style
and index
prop to our Row
component by default
Now with everything in place, let’s check out our FPS
meter. This time it is much closer to our goal of 60fps
.
If you have cloned the repo and compared the two branches, you will also see just how much quicker the initial render is. To prove this, let’s run another audit.
Initially we scored 63
in our performance, but now we have scored 100
. Our First Meaningful Paint
took only 1.1s
, compared to 4.8s
without react-window
. Also remember that this audit was ran against 5000
movies, not the 500
the initial audit was ran on.
You can see from the above just how powerful react-window
is. Our application was a very simple one but we can still see great performance benefits. I hope you have learned something from this article and are closer to achieving your performance goals.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!