Virtualized Lists in React
In this article I want to describe how you can useList
and Autosizer
from react-virtualized
. An advantage of using virtualized
lists is that only visible rows are rendered into the DOM whereas the other rows are rendered only when they become visible by scrolling into the list. This could be of great help when you are working with large arrays with 1000 -10,000 records and you don’t want to keep the whole element list into the DOM, because this could lead to massive performance problems.
We will create a large set of data using faker.js
that we will display. faker.js
is a library that helps create random data by calling a few simple methods. The records contain information about articles having a type, title, description, image and notes.
const generateType = () => {
return Math.floor(Math.random() * 10) % 2 === 0 ? "article" : "question";
}
const generateEntry = () => {
return {
type: generateType(),
title: faker.lorem.sentence(),
description: faker.lorem.paragraph(),
image: faker.image.image(),
notes: faker.lorem.paragraph(),
}
}export function getAllPosts(nrOfRecords) {
let allPosts = [];
while (allPosts.length < nrOfRecords) {
const entry = generateEntry();
allPosts.push(entry);
}
return allPosts;
}
In order to create an array with 1,000 elements we will call the getAllPosts
method like this:
const allPosts = getAllPosts(1000);
The Autosizer
will return information about height and width to the List
. You need to be careful here, because in case height or width returns 0 it could be coming from one of its parents div which has a height or a width of 0 and the List will not enlarge if at least one of its parents has a height or a width of 0. You can fix this issue by setting its parents height to height: 100%
or by using flex: 1
on the parent as recommended in the react-virtualized
documentation which can be found here.
<AutoSizer>
{({height, width}) => (
<List
height={height}
width={width}
itemCount={allPosts.length}
rowHeight={rowHeight}
rowCount={allPosts.length}
rowRenderer={renderPost}
>
</List>
)}
</AutoSizer>
The rowRenderer
property is used to render the row, whereas the rowHeight
will be used to compute the height of the row in case you need different heights for a row.
const renderPost = (item) => {
const {index} = item;
return allPosts[index].type === "article" ? <ArticlePost article={allPosts[index]} item={item}/> :
<SimplePost article={allPosts[index]} item={item}></SimplePost>;
};
For the case when the item displayed is an article and not a question the height will be bigger and this can be controlled from the rowHeight
property.
const EXPANDED_ROW_SIZE = 250;
const ROW_SIZE = 200;const rowHeight = (item) => {
const {index} = item;
return allPosts[index].type === "article" ? EXPANDED_ROW_SIZE : ROW_SIZE;
};
The rendered list will look like this and you can see that the heights of the rows are different for the items depending on their type. When scrolling on the page you can notice when inspecting the elements how the elements are added and removed from the DOM.
The code source of this project can be found in github
at the following repository.
I hope this article helps you get a better understanding on how virtualized
lists are working and how they are helpful. Let me know what you think.
Thank you!
Special thanks to Bogdan Bucsa for his great input on virtualized
lists in React.