React list rendering: when basic patterns break at enterprise scale
Most React tutorials cover the basics: use map() for lists, add key props, call it done. This works until your dashboard needs to display 50,000 transaction records or a logging interface streams thousands of events.
The fundamental issue is that React will try to render every item in the array, even if only 20 are visible on screen. With large datasets, this creates genuine performance problems: slow initial renders, janky scrolling, and browser memory issues.
When virtualization matters
Virtualization libraries solve this by rendering only the visible items plus a small buffer. Scroll down, and they swap out DOM nodes instead of creating new ones. The technique has been standard in enterprise applications for years.
Three libraries handle most production use cases:
react-window is the current default choice. Lightweight, well-maintained by Brian Vaughn (ex-React core team), handles fixed and variable height lists. Good documentation, active community. Works in Next.js without issues.
react-virtuoso handles dynamic heights better out of the box. Particularly useful when item heights aren't known upfront or change based on content. Slightly larger bundle size, but the API is cleaner for complex scenarios.
react-virtualized is the older library that started the category. Still works, still maintained, but most new projects use react-window instead. The API is more complex and the bundle size is larger.
The variable height problem
Fixed-height lists are straightforward. Variable heights get complicated because the library needs to calculate scroll positions without rendering everything. react-window's VariableSizeList requires you to provide item heights upfront or measure them. react-virtuoso handles this automatically by measuring as it renders, which is easier to implement but slightly less performant.
For infinite scrolling with pagination, react-window's InfiniteLoader component works reliably. You provide a function to load more data when the user scrolls near the bottom. The pattern is standard enough that most implementations look similar.
What actually matters in production
Profile before optimizing. Chrome DevTools' Performance tab shows render times clearly. If your list renders in under 100ms and scrolling is smooth, basic rendering is fine. If scrolls drop frames or initial render takes seconds, virtualization is the fix.
The key prop still matters with virtualization. Use stable, unique identifiers. Index-based keys cause issues when items are added or removed from the middle of the list.
Most enterprise applications end up with react-window for standard lists and react-virtuoso when dealing with user-generated content where heights vary significantly. Both handle tens of thousands of items without issues.
The real complexity isn't choosing a library, it's handling the edge cases: maintaining scroll position during updates, handling items being added above the viewport, managing focus for accessibility. These problems exist regardless of which library you use.
Virtualization is a solved problem. The libraries work. Choose one, implement it properly, move on to the actual business logic.