Virtualise large data lists easily with react-window
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:
- Reduce page loading because only the data directly visible on the screen by the user is loaded;
- Improve fluidity because fewer data elements are present in the DOM, so the browser has less work to do to scroll through a page;
- 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:
- 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;
- Improved performance - Enabling virtualization, as we saw, greatly improves the page loading performance (and we love that!) ;
- 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:
npm install react-window
Or if you prefer yarn:
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:
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.
["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 listitemCount
- the total number of items in our complete listitemSize
- the height of each itemwidth
- 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:
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 specifyinglayout="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:
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:
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
.
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! 🙄