Library / SDK
petyosi/react-virtuoso avatar
petyosi/react-virtuoso

react-virtuoso: a virtual list component for React that measures items itself

The most powerful virtual list component for React

6,463 stars356 forksTypeScriptLicense varies

At a glance

What is it?
react-virtuoso is a React virtualization library built around variable-height items, with separate components for chat message lists, grouped lists, grids, masonry and tables. It fits teams rendering long feeds in the browser, and it is the wrong choice when you need a maintained release cadence you can pin to a versioning policy.
Who is it for?
Adopt react-virtuoso when you are rendering long, variable-height lists in React and you would rather let the component measure items than write your own height cache.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What react-virtuoso solves, and who ends up using it

Rendering ten thousand rows into a React tree is slow because every row becomes a DOM node, even the ones far outside the viewport. Virtualization fixes that by mounting only the visible slice. The hard part is not the slicing, it is the measurement: real data has rows of different heights, and a virtualizer that assumes a fixed row height produces a scrollbar that jumps and a scroll position that lies.

react-virtuoso takes the position that you should not have to measure anything yourself. The README states that variable sized items work out of the box and that no manual measurements or hard-coding item heights is necessary. That single decision is the reason to pick it over a lower-level virtualizer: you hand it a count and a render function, and it works out the rest.

The audience follows from that. Chat and messaging interfaces, activity feeds, comment threads, product listings and image galleries all have unpredictable row heights and all need the scroll position to stay honest when content above the viewport changes size. The repository topics list chat, feed and virtualizedlist alongside react, which matches the component set.

The library is not one component. The README describes a family: Virtuoso for flat lists, GroupedVirtuoso for lists with headers, VirtuosoGrid for same-sized items in columns, Masonry for varying-height columns, TableVirtuoso for HTML tables, and a separate message list component built for human and chatbot conversations. Choosing react-virtuoso usually means choosing one of those rather than the generic one.

How the component decides what to render

The public surface is deliberately small. Virtuoso takes totalCount, which is how many items exist, and itemContent, a callback that receives a zero-based index and returns the React node for that row. There is no items array. The component asks you for item 4,371 when it needs item 4,371, and it does not hold your data.

That inversion matters for data flow. Infinite scrolling, pagination and live updates all become your problem at the data layer, and the component only has to be told that the count grew. The README lists endless scrolling and press to load more as supported patterns, and both are described as behaviours you configure on the component rather than data sources it fetches.

GroupedVirtuoso changes the contract in one specific way. Instead of totalCount you pass groupCounts, an array where each number is the size of one group; the README gives [20, 30] as an example, meaning two groups with 20 and 30 items. You then supply a second callback, groupContent, which receives the zero-based group index and renders the group header. Sticky headers are a consequence of that split, not a separate feature.

The message list component is architecturally different from the rest. The README describes an imperative data management API on top of the virtualized rendering, exposed so that you can control scroll position when older messages are loaded, when new messages arrive, and when the user submits a message. That is a real distinction: the flat Virtuoso is declarative, and the message list expects you to call into it.

VirtuosoGrid is the odd one out in the other direction. It displays same sized items in multiple columns, and the README says layout and item sizing are controlled through CSS class properties, which is what lets you use media queries, min-width and percentages. If your grid items have unpredictable heights, that component is the wrong one and Masonry is the one the README points at.

Installing react-virtuoso and rendering a first list

The README gives a single install command and no peer dependency list, so the package manager resolves React from your project.

bash
npm install react-virtuoso

After that, the README's own example imports the named Virtuoso export and renders it with a fixed height container, a totalCount and an itemContent callback. The style height is not decoration: the component needs a bounded box to know what the viewport is.

jsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { Virtuoso } from 'react-virtuoso'

const App = () => {
  return <Virtuoso style={{ height: '400px' }} totalCount={200} itemContent={(index) => <div>Item {index}</div>} />
}

ReactDOM.render(<App />, document.getElementById('root'))

What you should see is a 400-pixel scrollable box containing 200 rows, with only a fraction of them present in the DOM at any moment. The README does not document a CSS import step, which is consistent with the grid component's sizing being driven by class properties you supply rather than by a stylesheet the package ships.

Once that renders, the next thing to change is the height of the rows. Give itemContent a node whose height depends on the index and scroll: the README's claim is that no hard-coded heights are needed, so this is the experiment that either confirms the library fits your data or tells you it does not. For a table, TableVirtuoso works like Virtuoso but renders HTML tables, and the README says it supports window scrolling, sticky headers and sticky columns, and works with Tanstack Table and MUI Table.

Where react-virtuoso stops being the right tool

The README's feature list is a list of supported layouts, not a list of supported environments. There is no mention of server-side rendering, no mention of React Native, and no statement about what happens when the component mounts in an environment without a layout engine. If your rendering target is not a browser DOM, the README gives you nothing to work with, and you should treat that silence as a boundary rather than an oversight to work around.

The second limitation is the measurement model itself. Variable-height items out of the box is the headline feature, and it is also the source of the cost: the component has to observe and correct as content changes. The README lists automatic handling of content resize as a feature, which tells you the library is doing work on resize, but it does not describe the algorithm, the reflow cost, or how it behaves when a row's height changes while that row is off-screen. For a list of a few hundred rows, a plain map over your array is simpler and has no such machinery.

The third is versioning. The current release is [email protected], and the repository also publishes @virtuoso.dev/reactive-engine-storage at 4.0.0 and @virtuoso.dev/reactive-engine-router at 2.0.0. Three packages at three different major versions is a normal monorepo outcome, but it means a bug report needs the package name as well as the version. The README does not document rollback, deprecation windows, or a migration path between majors, and the changelog tooling lives in a .changeset directory rather than in the README. If your organisation requires a documented support policy before you take a dependency, that policy is not stated in the README.

Finally, the licence section. The README ends with a single line, MIT License, and the repository metadata does not carry a licence identifier. MIT is permissive, but nothing here states how the licence file is wired into the published packages, and that is a question for whoever handles your dependency review rather than something this article can settle.

react-virtuoso vs react-window and TanStack Virtual

The alternatives people actually weigh are react-window and TanStack Virtual, and the difference is where the measurement logic lives.

react-window asks you to declare the size of an item up front. It is a small, focused package, and the reason to choose it is that the size is genuinely knowable: uniform rows, a fixed row height, a table where every cell is one line. When that assumption holds, the declared size is cheaper than any measurement pass, and the extra machinery in react-virtuoso is overhead you are paying for nothing.

react-virtuoso inverts the assumption. The README's first bullet is that variable sized items work out of the box and that no manual measurements or hard-coding item heights is necessary. That is the trade: you give up control over the measurement strategy and you get back the work of writing one.

TanStack Virtual sits at a different level again. It is a headless virtualizer, meaning it computes ranges and you own the markup entirely. react-virtuoso ships the components, and the README's answer to markup control is customization rather than headlessness: it lists custom header, footer and empty list components, and points at a Material UI infinite scrolling demo under third-party integration, plus TableVirtuoso working with Tanstack Table and MUI Table. If your design system needs a DOM structure the library does not produce, headless is the shorter path; if you want the list to exist after you pass a count, react-virtuoso is.

The message list is the case where the comparison stops being close. The README describes it as built specifically for human and chatbot conversations, with an imperative API for scroll position when older messages load, new messages arrive, and the user submits. Neither react-window nor a headless virtualizer gives you that as a component; you would assemble it from scrollToIndex, initial top most item index and pinned top items, all of which react-virtuoso also exposes for the flat component.

Maintenance, releases and what an upgrade actually costs

The repository is not archived. The last push was on 2026-09-20, and the most recent react-virtuoso release, 4.18.14, was published on 2026-09-20 as well. Two other packages in the monorepo, @virtuoso.dev/reactive-engine-storage and @virtuoso.dev/reactive-engine-router, were published on 2026-09-20 at versions 4.0.0 and 2.0.0. That is a same-day cluster, which is what a coordinated monorepo release looks like.

The upgrade cost is visible in the repository layout rather than in the README. The root package.json defines a release script that builds first and then runs changeset publish, and a changeset-version script that runs changeset version followed by a sync-version filter on @virtuoso.dev/virtuoso-skills. Changesets are the mechanism, so version bumps and changelog entries are generated from committed changeset files, not hand-written. If you track releases, watching the .changeset directory tells you what is coming before the version number moves.

The CI pipeline is worth reading before you assume a fast fix. The ci script chains ci-setup, format:check, build, typecheck, lint, lint:md, test and e2e in sequence, and the per-package lint, test and e2e scripts run with --no-bail, meaning failures in one workspace do not stop the others. That is a reasonable choice for a monorepo and it also means a green CI run is not proof that every package passed.

On licence: the README states MIT License. MIT permits commercial use and modification, and it requires that the copyright notice and permission notice be preserved. That is the whole of what the README supports. Whether your organisation accepts MIT for a UI dependency, and how the notice is carried into a bundled application, is a question for your own review process.

The README also asks for sponsorship, noting that support helps ensure continued development and maintenance. That is a funding request, not a support contract, and it does not change what you can expect from an issue.

Editorial conclusion

Adopt react-virtuoso when you are rendering long, variable-height lists in React and you would rather let the component measure items than write your own height cache. Do not adopt it if you need a documented semantic-versioning guarantee, a supported older major, or any statement about backward compatibility across majors: the README does not document rollback, deprecation windows or migration steps between major versions, and the changelog lives in a .changeset directory rather than in the README. Before you commit, run npm install react-virtuoso, render a single Virtuoso with totalCount and itemContent against your real data shape, and check that the container you give style height is the one that actually scrolls in your layout. Verify that the docs site covers the component variant you picked, because the README links out to virtuoso.dev for every feature beyond the flat list.

Frequently asked questions

How do I use react-virtuoso in a React app?

Install it with npm install react-virtuoso, import the named Virtuoso export, and render it with a bounded height container, a totalCount and an itemContent callback that receives the item index. The README's example uses style={{ height: '400px' }} with totalCount={200}.

What is react-virtuoso?

It is a React virtualization component family. The README describes it as the most complete React virtualization rendering family of components, covering flat lists, grouped lists with sticky headers, grids, masonry, tables and a chat message list.

Is react virtuoso free?

The README states the licence as MIT License. MIT permits commercial use and modification provided the copyright and permission notice are preserved. The README also asks for optional sponsorship to support continued development.

How does react-virtuoso compare with react-virtualized?

The README does not describe react-virtualized's approach, so a direct comparison is not possible from it. What the README does state is that react-virtuoso handles variable sized items out of the box with no manual measurements or hard-coded item heights.

Official sources

  1. Issues
  2. petyosi/react-virtuoso on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/petyosi-react-virtuoso.svg)](https://hysenlabs.com/projects/petyosi-react-virtuoso)