Getting to Grips with react-window

Paul Ryan

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.

The Theory Behind react-window

react-window in theory is very simple to understand, the window refers to the view the user can see.

Window View

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!

✨ Black Friday - 50% off all of Wes Bos' courses

Recommended React and GraphQL course

Let’s Get Practical

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

Our App

Initial Measurements

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.

FPS Meter

Our Frame Rate is at 34.0 fps which is quite slow, we are more looking for achieving something around 60fps.

Frame

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

Audit

As you can see from the above, the performance is not good and remember this is with 500 movies, not 5000.

Implementing react-window

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';

Creating a Row

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.

AutoSizer Component

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';

List Component

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.

Good Frame Rate

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.

Good 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.

Wrapping Up

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.

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#