React virtualized infinite scrolling table, how to

infinite scrolling react react virtualized

React Virtualized is a nice lib providing interesting components used to manage large amount of data.

It is also quite well documented and comes with some examples, but the components are somewhat complex at a first sight, and it's not a 5 minutes lib, in a world when you have 10 minutes to develop an entire project. So it may be scaring at the beginning, but if you just have the time to fully understand how it works you'll see that is not so scaring at the end.

I've used it in some situations till now, the last one was while developing  a sort of logs table. So I need a table representing a large amount of data, paginated with infinite scrolling. This is the scenario I want to talk about in this post, but I won't just paste the final code here, instead we'll proceeed step by step in order to get a better understanding of the components used, and why they're used.

So the first step of course is: we need a table!

Create a simple table with React Virtualized

The library provides a table component, here we may find the reference. A table is made up of columns. The columns are children of the Table component. The Table component has some required props:

  • headerHeight: the height of the table header
  • height: the height of the table
  • rowCount: the number of rows
  • rowGetter: a function that given the row index returns the row object (we'll see how this is consumed by the columns)
  • rowHeight: the height of a row
  • width: the width of the table

While a column ha the following required props:

  • dataKey: the key name of the row object (see above) used to retreive the value inserted in the cell
  • width: the column width

Ok, quite straightforward, isn't it? I've prepared a codepen example to show a demo, here it is. I've used faker to fake the data and I've put them straight in the state, in a real world application probably the data are managed in a redux store or anyway passed as props from a parent component.

See the Pen react virtualized simple table example by abidibo (@abidibo) on CodePen.

Basically, the Table component will call the rowGetter function for every rowCount, retrieves an object and uses the dataKey prop of the Column component to retrieve the value to put in the cell.

Nice, but there's too much hardcoded stuff

We've created our table and that's ok, but there are some things I don't like at all, some things that sucks in a real world application. In particular I find ridiculous nowadays to be forced to specify a width for something. But the Table component needs a width, so how can we make it dynamic?

The answer comes from React Virtualized again, in fact it provides an HOC called AutoSizer which does just that: wraps the child component giving it the calculated available width. It work also for the height, and I've used it with success, but here I'll focus on width only, since in the pen example you wouldn't appreciate the height stuff.

See the Pen react virtualized autosize table example by abidibo (@abidibo) on CodePen.

So far so good. Now we have a dynamic width table, if you try resizing the window in the pen page, you'll see the table behaves adjusting its width. The AutoSizer component is an HOC which makes use of the render props pattern to inject the dynamic width into its child (in a few words, the child is a function receiving the width as argument and returning the table component which consumes such width). I've used the width also to calculate the columns width (20% for the id column, 40% for the name column and 40% for the e-mail column).

Adding the Infinite Loader

And now the last and trickiest part: we need to add infinite scrolling, and we do this using the InfinteLoader component provided by the library. Let's see the required props:

  • isRowLoaded: is a function that gets the row index and must say if the row data are already loaded or not
  • loadMoreRows: is a function that receives the startIndex and stopIndex  and should return a Promise that should be resolved once the new data area loaded (here I wont use such params since I just ask for some more faked data)
  • rowCount: the number of rows (set it very high if you don't know the exact number)

The pen:

See the Pen react virtualized infinite loader autosize table example by abidibo (@abidibo) on CodePen.

Here may be necessary to spend a few words on what's going on. The InfiniteLoader children function receives two params:

  • onRowsRendered: this function should be passed as the child's onRowsRendered property. It informs the loader when the user is scrolling
  • registerChild: this function should be set as the child's ref property. It enables a set of rows to be refreshed once their data has finished loading

The loadMore prop should be a function which returns a Promise resolved when the data have actually been fetched. The Promise can be rejected if there's nothing more to load or if for any other reason you don't want to load more rows (think of a refresh/freeze state, that was my case).

I hope this was useful to you. I've not found any resource on the web presenting a complete example of infinite scrolling of a react virtualized table, so I decided to write it down, this will be useful to me when, in the next future, I'll need to use these components again and, meanwhile, my memory got flashed as always happens.

Let me know your opinions and if you enjoyed the article, share it with the world!

Subscribe to abidibo.net!

If you want to stay up to date with new contents published on this blog, then just enter your email address, and you will receive blog updates! You can set you preferences and decide to receive emails only when articles are posted regarding a precise topic.

I promise, you'll never receive spam or advertising of any kind from this subscription, just content updates.

Subscribe to this blog

Comments are welcome!

blog comments powered by Disqus

Your Smartwatch Loves Tasker!

Your Smartwatch Loves Tasker!

Now available for purchase!