Sensidev logo
Hero Image

List Virtualization in React

by Alex Sîrbuabout 4 years ago 4 min read

While working on our Sensix live dashboard, we ran into a classic rendering problem. As you can see from the gif, our metric list can get pretty large.

Even though we only load more metrics upon reaching the end of the list, the size can easily skyrocket. The problem presents itself when changing pages and going back. Rendering an extensive amount of DOM nodes in one pass was taking seconds, and it felt awful.

The solution was obvious, virtualization to the rescue. Virtualizing or windowing a list means rendering just enough items to fill the viewport, loading more upon scrolling.

In React , there are 2 open source virtualization solutions, react-virtualized and react-window . If you’re wondering what’s the difference between them, here’s the author’s explanation:

“I wrote react-virtualized several years ago. At the time, I was new to both React and the concept of windowing. Because of this, I made a few API decisions that I later came to regret. One of these was adding too many non-essential features and components. Once you add something to an open source project, removing it is pretty painful for users. react-window is a complete rewrite of react-virtualized. I didn't try to solve as many problems or support as many use cases. Instead I focused on making the package smaller and faster. I also put a lot of thought into making the API (and documentation) as beginner-friendly as possible (with the caveat that windowing is still kind of an advanced use case).”

Because our use case requires window scrolling, we chose the former. Before we build the list, we need to import the components and the base styles from the package.

import { List, WindowScroller } from 'react-virtualized';
import 'react-virtualized/styles.css';

The WindowScroller component provides some properties that need to be assigned to the List component, along with some dimension constraints: the number of rows in the list, the height of a row, the width of the list, and a renderer function for each row.

<WindowScroller>
    {({ height, scrollTop, onChildScroll }) => (
        <List
            autoHeight
            height={height}
            rowCount={50}
            rowHeight={100}
            rowRenderer={rowRenderer}
            scrollTop={scrollTop}
            width={1000}
            onScroll={onChildScroll}
        />
    )}
</WindowScroller>

The rowRenderer function uses the style prop to position the rows, so that needs to be assigned to the parent of each row. The index prop can be used to pass data to each list item.

function rowRenderer({ key, index, style }) {
    return (
        <div key={key} style={style}>
            {list[index]}
        </div>
    );
}

Conclusion:

While React is very fast on its own, browsers have their limitations and rendering a very large DOM tree is still slow. Virtualization helps bypass this limitation, displaying only a batch of items at a time.

Dev Thoughts