Believemy logo purple

Virtualise large data lists easily with react-window

Find out how to effectively virtualise large lists of data using react-window and improve your users' experience.
Updated on December 8, 2024
Believemy logo

Effectively managing large data lists can quickly become very complicated in a React application: the more data there is to display, the more performance will be impacted.

When thousands of items need to be displayed (such as a list of registered users or a list of articles): it’s catastrophic for the user experience, with a browser trying to keep up and ending up crashing one out of three times. 🥲

Fortunately, there is a solution: react-window

This is a React library very handy for managing large amounts of data. We’re talking about virtualization.

When we talk about virtualizing something, it means that we will only display a small portion of the elements visible in the viewport (the browser window).

Virtualization has several advantages:

  1. Reduce page loading because only the data directly visible on the screen by the user is loaded;
  2. Improve fluidity because fewer data elements are present in the DOM, so the browser has less work to do to scroll through a page;
  3. Boost the user experience because the user ends up with a page that loads quickly.

 

Why Use react-window?

The advantages of react-window are numerous for React developers who need to manage large amounts of data in their projects:

  1. Extremely lightweight and very fast - Compared to other libraries like react-virtualized, with which it is often compared (we’ll discuss it just after), react-window is much lighter;
  2. Improved performance - Enabling virtualization, as we saw, greatly improves the page loading performance (and we love that!) ;
  3. Supports different types of lists - In the form of grids, horizontal or vertical lists, everything is supported by react-window without any issues.

 

Installing react-window

To start using react-window, you need a React-based project (no joke 🙃).

Once that's done, simply install the library with npm:

CONSOLE
npm install react-window

Or if you prefer yarn:

CONSOLE
yarn add react-window

 

Create a List with react-window

Lists are the most commonly used formats for displaying data. They allow adding all elements one by one below each other.

Create a Fixed-Size List with FixedSizeList

The main component of react-window is the FixedSizeList component. It allows displaying a list of fixed-size elements.

Let’s look at a small example:

JSX
import React from 'react';
import { FixedSizeList as List } from 'react-window';

const items = Array(5000).fill().map((_, index) => `Item ${index + 1}`);

function Row({ index, style }) {
  return (
    <div style={style}>
      {items[index]}
    </div>
  );
}

export default function App() {
  return (
    <List
      height={500}
      itemCount={items.length}
      itemSize={40}
      width={500}
    >
      {Row}
    </List>
  );
}

In this example, we use a 5000-element list (Array(5000)) which we fill to provide a generic list that we can work with.

CONSOLE
["Item 1","Item 2","Item 3","Item 4","Item 5","Item 6","Item 7","Item 8","Item 9","Item 10","Item 11","Item 12","Item 13", ...]

We then use the FixedSizeList component renamed to List according to best practices:

  • height - defines the visible height of the list
  • itemCount - the total number of items in our complete list
  • itemSize - the height of each item
  • width - also defines the visible width of the list

Thanks to the FixedSizeList component, we now have a list of 5000 elements that displays in the blink of an eye!

If you prefer to display a horizontal list that allows scrolling like a slider (like Netflix), you can do so! Just add the layout property:

JSX
<List
        height={500}
        itemCount={items.length}
        itemSize={40}
        width={500}
        layout="horizontal"
    >
    {Row}
</List>

 

Create a Variable-Size List with VariableSizeList

Often, our items do not have a fixed size: therefore, we cannot use FixedSizeList.

Fortunately, another option offered by react-window is to use the VariableSizeList component (the name says it all 😋).

This component allows you to manage variable sizes. Here is an example:

JSX
import React from 'react';
import { VariableSizeList as List } from 'react-window';

const items = Array(5000).fill().map((_, index) => `Item ${index + 1}`);

function getItemSize(index) {
  return 30 + (index % 10) * 10; // Example of variable size
}

function Row({ index, style }) {
  return (
    <div style={style}>
      {items[index]}
    </div>
  );
}

export default function App() {
  return (
    <List
      height={500}
      itemCount={items.length}
      itemSize={getItemSize}
      width={500}
    >
      {Row}
    </List>
  );
}

In this example, all the items in our list have a different size calculated using the getItemSize function.

As with FixedSizeList, you can request a horizontal layout by specifying layout="horizontal" 🙂

 

Create Grids with react-window

In addition to lists, react-window allows managing data grids with the FixedSizeGrid and VariableSizeGrid components. Presented in table form, these components are very useful for displaying data with rows and columns.

Create a Fixed-Size Grid with FixedSizeGrid

Here’s how to create a fixed-size grid with react-window:

JSX
import React from 'react';
import { FixedSizeGrid as Grid } from 'react-window';

function Cell({ columnIndex, rowIndex, style }) {
  return (
    <div style={style}>
      {`Row ${rowIndex}, Column ${columnIndex}`}
    </div>
  );
}

export default function App() {
  return (
    <Grid
      columnCount={100}
      columnWidth={100}
      height={500}
      rowCount={100}
      rowHeight={35}
      width={500}
    >
      {Cell}
    </Grid>
  );
}

In this example, a grid of 100 cells wide by 100 cells tall is displayed! This could cause some slowdowns for the browser, but not with react-window which only loads the cells that are visible on the screen.

To go into detail:

  • columnCount - this property specifies the total number of columns in the grid (here 100 columns);
  • columnWidth - specifies the width of each column in pixels (100 pixels in the example);
  • height - indicates the total height of the grid in pixels;
  • rowCount - specifies the number of rows in the grid;
  • rowHeight - defines the height of each row in pixels;
  • width - indicates the total width of the grid in pixels.

Thanks to these parameters, the grid will display a subset of the elements.

Only the 5 columns (100 pixels each) out of the 100 total columns will be visible at any given time. When the user scrolls horizontally, new columns will be rendered in the DOM.

Similarly, only 14 rows (35 pixels each) out of the 100 rows will be visible at any given time in the window (since it is 500 pixels in height).

With a real example, here’s what we could have to display our registered users on our website:

JSX
import React from 'react';
import { FixedSizeGrid as Grid } from 'react-window';

const users = [
  { userId: 1, firstName: 'John', lastName: 'Doe' },
  { userId: 2, firstName: 'Jane', lastName: 'Smith' },
  { userId: 3, firstName: 'Paul', lastName: 'Johnson' },
  // etc
];

// Number of columns (id, first name, last name)
const columnCount = 3;

// Width of each column
const columnWidth = 150;

// Height of each row
const rowHeight = 40;

// Total visible grid width (based on 3 columns)
const gridWidth = columnCount * columnWidth;

// Total visible grid height (example of 6 visible rows)
const gridHeight = 6 * rowHeight;

function Cell({ columnIndex, rowIndex, style }) {
  const user = users[rowIndex];
  
  // Determines what content to display based on the column index
  let content;
  switch (columnIndex) {
    case 0:
      content = user.id;
      break;
    case 1:
      content = user.firstName;
      break;
    case 2:
      content = user.lastName;
      break;
    default:
      content = '';
  }

  return (
    <div style={style}>
      {content}
    </div>
  );
}

export default function App() {
  return (
    <Grid
      columnCount={columnCount}
      columnWidth={columnWidth}
      height={gridHeight}
      rowCount={users.length}
      rowHeight={rowHeight}
      width={gridWidth}
    >
      {Cell}
    </Grid>
  );
}

In this example, all the lines are explained so that you can follow along. What you need to remember is that it is sufficient to use the item index to correctly place the associated information (here, about a user). 😬

 

Create a Variable-Size Grid with VariableSizeGrid

To work with variable-sized items in a grid, you can use the VariableSizeGrid component provided by react-window.

In this example, we will use columns to display id, firstName, and lastName (I deliberately used French to make this topic a bit more complex yet accessible to as many as possible 😋), but each column and each row will have a different size, which is managed by VariableSizeGrid.

JSX
import React from 'react';
import { VariableSizeGrid as Grid } from 'react-window';

// Example user data
const users = [
  { userId: 1, firstName: 'John', lastName: 'Doe' },
  { userId: 2, firstName: 'Jane', lastName: 'Smith' },
  { userId: 3, firstName: 'Paul', lastName: 'Johnson' },
  // etc
];

// Function to return the width of each column dynamically
const getColumnWidth = (index) => {
  switch (index) {
    case 0: // id
      return 100;
    case 1: // first name
      return 150;
    case 2: // last name
      return 200;
    default:
      return 100;
  }
};

// Function to return the height of each row
const getRowHeight = (index) => {
  return 40 + (index % 3) * 10; // Here with a variable height
};

function Cell({ columnIndex, rowIndex, style }) {
  const user = users[rowIndex];
  
  // Determines what content to display based on the column index
  let content;
  switch (columnIndex) {
    case 0:
      content = user.id;
      break;
    case 1:
      content = user.firstName;
      break;
    case 2:
      content = user.lastName;
      break;
    default:
      content = '';
  }

  return (
    <div style={style}>
      {content}
    </div>
  );
}

export default function App() {
  return (
    <Grid
      columnCount={3} // Three columns: id, first name, last name
      columnWidth={getColumnWidth} // Column widths defined dynamically
      height={400} // Visible grid height
      rowCount={users.length} // Number of rows = number of users
      rowHeight={getRowHeight} // Row heights defined dynamically
      width={500} // Visible grid width
    >
      {Cell}
    </Grid>
  );
}

In this example, all our users have a different height calculated by getRowHeight and a different cell width calculated based on the information to display: id, firstName, or lastName.

 

Conclusion

React-window is truly a powerful and lightweight solution for effortlessly managing large data lists!

As we’ve seen, the library can just as well handle displaying lists as it can handle grids.

Although mastering it takes some time, it’s a real must-have for all projects that aim to improve the user experience.

 

FAQ

We’ve condensed for you the most frequently asked questions our learners ask us when they talk about react-window! 😬

What is the difference between react-window and react-virtualized?

They are often compared! react-window is lighter and more performant for most use cases. react-virtualized offers more features, but is much more complex to set up and is also heavier: which goes against what we’re looking for.

Created by the same developer, react-virtualized was the first one; react-window was created later to balance the complexity of react-virtualized.

So if you want a little advice: use react-window instead of react-virtualized. 😉

 

What are the advantages of virtualization?

Virtualization allows you to render only the elements visible in your DOM, which improves performance, especially when rendering long lists.

 

What is the maximum size allowed for using react-window?

Actually, there is none! You can use react-window for as much data as you want.

 

Is it possible to fetch data as the user scrolls through the list?

Yes! With a library developed by the developer of react-window: react-window-infinite-loader.

 

I want to continue learning React, which training should I choose? 🤔

Ours, of course! 🙄

Category: Development
Believemy logo
Comments (0)

You need to be logged in to comment on this article: log in or sign up.

Try for Free

Whether you're scaling your startup, building your first website, or transitioning to a developer role, Believemy is your new home. Join us, grow, and let’s build your project together.

Believemy is with anyone