In this article, we'll explore a technique called "cell-based virtualization" to smoothly handle tens of thousands of concurrent data grid rows in a React-based web application.
As web applications grow in complexity, the amount of data they need to manage also increases. This data is often presented in data grids, which allow users to view, edit, and manipulate rows of data. However, rendering thousands of rows in a data grid can cripple performance and lead to an unusable interface. In this article, we'll explore a technique called "cell-based virtualization" to smoothly handle tens of thousands of concurrent data grid rows in a React-based web application.
A naive data grid implementation might load all the data and render all the rows and cells at once. This works fine for small data sets, but as the number of rows grows, the interface slows to a crawl.
Some major performance issues include:
For example, a grid with 50,000 rows and 5 columns would need to render 250,000 cell elements on top of the row markup, JavaScript memory overhead per record, event handlers, and more. This taxes the browser and leads to severe lag when scrolling and interacting.
Virtualization techniques only render a small subset of rows that are currently visible, usually with some overflow on either side. As the user scrolls, rows are seamlessly rendered or removed as needed.
This helps performance by:
However, traditional virtualization operates at the row level – entire rows are rendered or removed as a block. This still requires layout and rendering of hundreds or thousands of cells at a time.
Cell virtualization takes things to the next level by only rendering the currently visible cells, rather than full rows. As the user scrolls, individual cells are rendered precisely where they need to be in the viewport.
For example, given a grid with 10,000 rows and 5 columns, traditional row virtualization might render 100 full rows with 500 visible cells. In contrast, cell virtualization could render just the 150 cells currently visible rather than full rows.
This further optimizes:
A cell-virtualized data grid also intelligently reuses existing cell elements as much as possible. As you scroll, most new cells can be efficiently swapped into place rather than created from scratch. This caching avoids expensive DOM placement and reflows.
Here is a simplified version of cell reuse logic in React:
By reusing elements, wasted recreation of identical markup is avoided. This optimization starts to become significant at scale across tens of thousands of records.
As a real-world test case, we implemented a React data grid using cell-based virtualization with the following parameters:
Even with this much raw data, cell virtualization provided a smooth 60 FPS scrolling experience. Memory usage remained reasonable for such a large dataset, and DOM elements were optimized by reusing cells.
Some numbers from Chrome DevTools:
Compare this to a naive rendering approach which would have likely crashed the browser!
Here is a high-level outline of how cell-based virtualization can be implemented:
Determine visible row range
Calculate visible cell range
Here is sample logic in React:
Populate container
Smooth scrolling
By following virtualization best practices, the grid stays responsive even with 100K concurrent records!
Cell-based data grid virtualization opens the door to managing large, real-time datasets in web UIs. Some ideas for taking things further:
Incremental loading – Fetch additional data as user scrolls down
Remote data – Integrate with large cloud data sources
Column virtualization – Only render visible columns
Dynamic columns – Reordering, resizing, etc
Immutable data – For snapshots, time travel debugging, etc
If you need to visualize or interact with huge numbers of records, give cell virtualization a try! Proper virtualization technique can make the difference between an unusable laggy interface and a buttery-smooth user experience.