Virtualization in React: The Technique for Handling 100,000 Data Rows Without Lag

You have a 50,000-row list to display in React. If you render everything at once, the browser has to build tens of thousands of DOM nodes—CPU and RAM struggle, the UI stutters badly, and Core Web Vitals plummet. Virtualization (or Windowing) solves this with a simple yet extremely effective principle.

virtualizationreact-windowwindowing
Cover image: Virtualization in React: The Technique for Handling 100,000 Data Rows Without Lag
Avatar of Trung Vũ Hoàng

Trung Vũ Hoàng

Author

1/4/20263 min read

1. What Is Virtualization?

Instead of rendering the entire list, Virtualization renders only the items currently inside the user’s visible area (viewport)—usually 10–20 items. When the user scrolls, old items are removed from the DOM and new items are inserted immediately.

The result: even with 100,000 records in your data, the real DOM still contains only about 10–15 nodes. UI response time drops from seconds to just a few milliseconds.

2. How It Works

A Virtualization library continuously calculates the scroll position to determine which items should be displayed. It also maintains a buffer of a few items outside the viewport—to prevent “blank gaps” when users scroll quickly before new rows have time to render.

From React’s perspective: Virtualization drastically reduces the number of nodes the reconciliation algorithm has to process after each re-render—making it a perfect complement to React’s Diffing mechanism.

3. Implementing with react-window

react-window is the go-to library for Virtualization in React—lighter and faster than its predecessor react-virtualized. Install it:

npm install react-window

Example: a 100,000-item list with fixed row height:

import { FixedSizeList as List } from 'react-window';

const Row = ({ index, style }) => (
  <div style={style} className={index % 2 ? 'row-odd' : 'row-even'}>
    Item #{index + 1}
  </div>
);

const MyList = () => (
  <List
    height={500}       // Viewport height (px)
    itemCount={100000} // Total items
    itemSize={50}      // Row height (px)
    width="100%"
  >
    {Row}
  </List>
);

With this configuration, only about 10–12 DOM nodes actually exist in the DOM at any time—no matter how large itemCount is.

4. Real-World Use Cases

Two-dimensional data grid

A table with hundreds of columns and thousands of rows—needs virtualization both horizontally and vertically. react-window provides FixedSizeGrid for this case.

Message list (Chat)

Scrolling back to older messages with uneven message heights—use VariableSizeList combined with measured-height caching.

Large searchable dropdown

A select box listing provinces/states, countries combined with a search input—Virtualization ensures the input doesn’t lag even when the list has thousands of options.

5. Important Notes

  • Use fixed height if possible: FixedSizeList is much simpler and faster than VariableSizeList. Design your UI with uniform row heights whenever you can.

  • Cache heights with VariableSizeList: Don’t measure the DOM on every scroll—cache measured results to avoid layout thrashing.

  • Accessibility (A11y): Ensure screen readers can still navigate the list—test with VoiceOver and NVDA.

  • Combine with useMemo: Wrap the data passed into the List in useMemo to avoid recreating arrays and triggering full re-renders.

Conclusion

Virtualization is the line between an amateur web app and a professional product. The principle is simple—render only what the user can see—but the performance impact is extraordinary:

  • DOM nodes: from tens of thousands down to ~15.

  • Render time: from seconds down to a few milliseconds.

  • Memory footprint: significantly reduced, with far less pressure on the Garbage Collector.

Any application that displays a list longer than 100 items should consider using Virtualization.

Frequently Asked Questions

Share this article
Zalo

Found this article helpful?

Contact us for a free consultation about our services

Contact us

Bài viết liên quan