react-virtuoso vs TanStack Virtual vs react-window: the 2026 Next.js comparison
All three shipped a release in September 2026 and all three are MIT. What separates them is how much of the component they hand you: five prebuilt components, two, or none at all. The library everyone quotes as 5KB is measured here at eleven times that.
On this page
Quick answer (September 2026). Pick TanStack Virtual if you are rendering anything that is not a plain list, because it gives you two hooks and no components and gets out of the way. Pick react-window if you want the smallest thing on the page that still renders itself, and you are already on React 18 or 19. Pick react-virtuoso if you want a table, a grid or grouped rows working this afternoon without writing the scroll container yourself. All three are MIT, all three were published in September 2026, and none of them is the wrong answer.
We checked all three against the live npm registry, the published tarballs and the GitHub API on 26 September 2026. Every number below is from that pass, not from a secondary article.
These three are not competing on the same axis
Most comparisons of these libraries argue about scroll performance. That argument is mostly settled: all three keep a windowed set of rows in the DOM, and on the list sizes a SaaS app actually renders, the difference is not something a user can perceive.
The real split is how much of the component they hand you. We counted the public exports in each published tarball rather than trusting the docs:
Scroll to see more
| Package | Renderable components | Hooks and helpers |
|---|---|---|
| 5 | 1 enum, 2 test contexts | |
| 2 | 6 | |
| 0 | 2 |
TanStack Virtual exports exactly useVirtualizer and useWindowVirtualizer. That is the entire public surface. It computes which items should be visible and what offset each one sits at, and you write every element yourself. react-window exports List and Grid plus six hooks. react-virtuoso exports Virtuoso, VirtuosoGrid, TableVirtuoso, GroupedVirtuoso and GroupedTableVirtuoso, so the table and grouping cases are already built.
If you pick on that axis first, the rest of this comparison is detail.
What you actually install
react-virtuoso and react-window both declare zero runtime dependencies. TanStack Virtual declares one, and it is the interesting one.
@tanstack/react-virtual depends on @tanstack/virtual-core, and it pins it to an exact version rather than a range: version 3.17.11, no caret. So you always get the core build the React binding was tested against, which is a genuinely nice property, but it does mean the two packages carry different version numbers even though they ship on the same day.
It also means the number people quote for TanStack Virtual is usually wrong. The React binding is a thin wrapper. Measured in the published tarball, @tanstack/react-virtual contains 5,150 bytes of ESM. The library is in @tanstack/virtual-core, which contains 52,407 bytes across three ESM files. Anyone telling you TanStack Virtual is a 5KB library is quoting the adapter.
Bundle size, measured from the published tarballs
We took the ESM build out of each published tarball and gzipped it ourselves. These are not bundler outputs, so treat them as an upper bound: tree shaking will remove whatever you do not import, and react-virtuoso in particular ships every component in one file.
Scroll to see more
| Package | ESM bytes | Gzipped |
|---|---|---|
| react-window 2.3.3 | 24,169 | 6,682 |
| TanStack Virtual (binding plus core) | 57,557 | about 11,955 |
| react-virtuoso 4.18.15 | 96,461 | 24,875 |
react-window is the smallest by a clear margin, and that ordering is exactly what the export counts predict. You pay in bytes for the components you did not have to write. If you only ever render a flat list, react-virtuoso is asking you to ship a table implementation you will never call.
The version 2 rename nobody warns you about
react-window 2.0.0 shipped on 28 August 2025, and it renamed the entire public API. The v1 names that every tutorial still uses, FixedSizeList and VariableSizeList, do not exist in the current package. There is one List and one Grid, and row height is handled by a useDynamicRowHeight hook rather than by choosing a different component.
This matters more than a normal rename because of where the documentation went. The current README points at a v1 documentation site for anyone still on the old API. We requested that site four times on 26 September 2026 and got HTTP 404 every time, while the current documentation site returned 200 on the same runs. The v1 docs host is gone.
The honest version of that finding is milder than it first looks, and worth stating plainly: v1 itself is fine. react-window@1.8.11 still installs from npm, and the v1 README is still readable in the repository at the 1.8.11 tag. What has disappeared is one hosted docs site, not the release. But if you are on v1 and you were relying on that link, you now have to read the tag.
There were 36 stable v1 releases, the last on 17 December 2024, and there have been 18 stable v2 releases since.
The React version gate
This is the constraint most likely to actually decide your choice, and it is buried in peerDependencies:
- react-window 2.3.3 accepts React 18 or 19 only.
- TanStack Virtual accepts React 16.8 and every major since.
- react-virtuoso accepts React 16 and every major since.
- react-virtualized accepts React 16.3 and every major since.
react-window v2 is the only one of the three that dropped React 16 and 17. If you are on an older React and cannot move yet, the choice is made for you, and it is not react-window. This is also the clearest practical reason the v1 line still has users.
Stars say one thing, downloads say another
We pulled both, and they disagree so completely that quoting either one alone would mislead.
Scroll to see more
| Package | GitHub stars | Weekly npm downloads |
|---|---|---|
| 27,073 | 2,005,697 | |
| react-window | 17,208 | 7,575,039 |
| TanStack Virtual | 7,122 | 27,191,513 |
| react-virtuoso | 6,461 | 3,857,037 |
The ranking inverts almost perfectly. react-virtualized has the most stars of anything in this space and was last published on 20 January 2025. TanStack Virtual has the fewest stars of the three live options and roughly 3.6 times react-window's download volume.
Stars are an accumulated historical total and they never go down. Downloads are a measure of the last seven days. When those two disagree this sharply, the star count is telling you what was popular when people were clicking the button, not what is being installed now.
One caveat we want to be explicit about, because it cuts against our own headline: npm download counts include continuous integration runs, registry mirrors and transitive installs, so they are not a headcount of developers. We checked the obvious explanation, which is that TanStack Virtual rides along as a dependency of other TanStack packages, and it does not hold: @tanstack/react-table, @tanstack/table-core, @tanstack/react-router and cmdk all declare no dependency on it. Its daily pattern is also 1.85 times higher on weekdays than weekends, which is what direct developer and CI usage looks like rather than a constant automated floor. So the number is large for ordinary reasons, but it is still an install count and not a popularity score.
The issue tracker number that is not what it looks like
react-window reports zero open issues. We checked that this is a real number and not a disabled feature: issues are enabled on the repository, it is not archived, and a separate search API query for open issues in that repository also returns zero.
But while checking it we found that the field most people quote is not an issue count at all. GitHub's open_issues_count includes pull requests. Separating them:
Scroll to see more
| Package | Open issues | Open pull requests |
|---|---|---|
| react-virtuoso | 47 | 8 |
| TanStack Virtual | 82 | 36 |
| react-window | 0 | 0 |
A genuine zero across 17,208 stars and 7.5 million weekly downloads is not an absence of problems. It is a maintainer triage policy, and it tells you that filing an issue is probably not how you will get help with react-window. TanStack Virtual's 82 open issues sit against the largest install base here, which is roughly what you would expect and not a warning sign on its own.
All three repositories were pushed to within the last five days: react-virtuoso and react-window on 22 September 2026, TanStack Virtual on 21 September 2026. None of the three is unmaintained.
The licences, read from the tarballs
All three are MIT, and we read each licence file out of the published tarball rather than trusting the registry metadata field, because a one word metadata field cannot express a condition even when one exists.
- react-virtuoso: MIT, copyright 2020 Petyo Ivanov. The full file is 1,068 characters and contains no added clause.
- TanStack Virtual: MIT, copyright 2021 to present Tanner Linsley.
- react-window: MIT, copyright 2018 Brian Vaughn.
One note on react-virtuoso, because it looks alarming from the outside and is not: the GitHub API reports no detected licence for that repository. The tarball contains a complete, unmodified MIT licence. That is a failure of GitHub's licence detector, not a licensing question.
Where react-virtualized and the newer options sit
Two more names come up often enough to place.
react-virtualized is the predecessor to react-window by the same author. It is still installed two million times a week, but it was last published on 20 January 2025, it carries six runtime dependencies against react-window's zero, and its unpacked size is 2.24MB. It is not a starting point for new work in 2026.
virtua is the interesting outlier: one package that declares peer dependencies on React, Vue, Svelte, Solid and Angular, at 1,207,607 weekly downloads. If you maintain front ends in more than one framework and want one virtualization mental model, it is worth a look. We have not benchmarked it against the three above.
Which one to pick
Work down this list and stop at the first one that matches.
- You are on React 16 or 17. Use TanStack Virtual or react-virtuoso. react-window v2 will not install.
- You need a virtualized table, a grid, or grouped rows, and you would rather not build the scroll container. Use react-virtuoso. You are buying five prebuilt components for about 25KB gzipped, and
TableVirtuosoalone will save you a day. - You are rendering something unusual: a chat log that grows upward, a timeline, a canvas, a masonry layout, anything where you control every element. Use TanStack Virtual. Two hooks, no opinions about your markup.
- You want a plain list or grid, on React 18 or 19, as small as possible. Use react-window. 6,682 bytes gzipped and zero dependencies is hard to argue with.
If you are still on react-window v1, the upgrade is a real rename rather than a version bump, and the migration documentation link in the README is dead. Read the README at the 1.8.11 tag before you start.
How we measured this
Every figure here came from one pass on 26 September 2026. Versions, dependency declarations, peer ranges and publish dates came from the npm registry API. Bundle sizes came from downloading each published tarball, extracting the ESM build and gzipping it locally, which is why we describe them as upper bounds rather than bundler output. Licences came from the licence file inside each tarball. Stars, push dates and issue counts came from the GitHub API, with open issues cross checked against the search API to separate them from pull requests. Download counts came from the npm downloads API. Search volumes, where mentioned, came from Google Ads data for the United States.
Where a number could be read two ways, we have said so in the text rather than picking the more dramatic reading.
Written by
Yui TanakaFrequently asked questions
Which React virtualization library has the smallest bundle?
react-window. We extracted the ESM build from each published tarball on 26 September 2026 and gzipped it: react-window 2.3.3 is 24,169 bytes raw and 6,682 gzipped, TanStack Virtual is 57,557 raw and about 11,955 gzipped once you include @tanstack/virtual-core, and react-virtuoso 4.18.15 is 96,461 raw and 24,875 gzipped. Treat these as upper bounds, since tree shaking removes whatever you do not import.
Is TanStack Virtual really only 5KB?
No. The 5,150 byte figure is @tanstack/react-virtual, which is a thin React binding. It depends on @tanstack/virtual-core, pinned to an exact version rather than a range, and that package holds the actual implementation at 52,407 bytes of ESM. The honest combined figure is about 57,557 bytes raw.
Does react-window v2 work with React 16 or 17?
No. react-window 2.3.3 declares a peer dependency on React 18 or 19 only. It is the only one of the three that dropped React 16 and 17. TanStack Virtual accepts React 16.8 and every major since, and react-virtuoso accepts React 16 and every major since. If you are stuck on an older React, react-window v2 is not available to you.
What changed between react-window v1 and v2?
The public API was renamed. Version 2.0.0 shipped on 28 August 2025 and replaced FixedSizeList and VariableSizeList with a single List component, plus a single Grid, and moved variable row heights to a useDynamicRowHeight hook. The v1 line ended at 1.8.11 on 17 December 2024 after 36 stable releases.
Is react-window abandoned? It has zero open issues.
No. It was published on 22 September 2026 and its repository was pushed to the same day. We confirmed the zero is real rather than a disabled tracker: issues are enabled, the repository is not archived, and a separate GitHub search query also returns zero. A genuine zero across 17,208 stars is a maintainer triage policy, not an absence of problems, so an issue is probably not how you will get help.
Why does react-virtualized have more GitHub stars than any of these?
Because stars accumulate and never go down. react-virtualized has 27,073 stars and was last published on 20 January 2025, carries six runtime dependencies against react-window's zero, and unpacks to 2.24MB. Weekly downloads tell the current story instead: TanStack Virtual 27,191,513, react-window 7,575,039, react-virtuoso 3,857,037, react-virtualized 2,005,697.
More from the garden
react-hook-form vs TanStack Form vs Formik: the 2026 Next.js comparison
Two of these three repositories were pushed to on the day we ran the check. The third was last pushed 312 days earlier, and the prerelease tag npm still advertises for it was published in December 2020.
dnd-kit vs Pragmatic drag and drop vs react-beautiful-dnd for Next.js in 2026
Three React drag and drop libraries, three different stages of life. Read from the npm registry, the published tarballs and the GitHub API on 16 September 2026: one is archived, one is quietly split in two, and one is not a React library at all.
Sonner vs react-hot-toast vs react-toastify for Next.js in 2026
Three React toast libraries whose reputations are all slightly wrong. Read from the npm registry, the published tarballs, the GitHub API and the live shadcn registry on 23 September 2026: the most downloaded one is the heaviest, the one with the steepest search decline shipped a release seven days ago, and the oldest has the best accessibility.