rc-virtual-list

React virtual scrolling list that renders only visible rows, used across the Ant Design ecosystem.

Library
npm
v3.19.2
815stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
78/100Good
Development Activity76
Maintenance84
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture84
Code Quality82
Innovation75
Learning Curve70

rc-virtual-list is a windowed list component for React that renders only the rows currently visible in the viewport, keeping scroll performance smooth even with tens of thousands of items. It measures item heights dynamically, falls back to real (non-virtual) scrolling when the data set is small, and ships a custom scrollbar with drag and touch support.

Maintained by the rc-component team behind Ant Design, it’s the underlying list engine for components like Select, Table, Tree, and Cascader across the Ant Design component family, but is published standalone so any React app can use it directly for large lists, feeds, or grids.

What You Get

  • A <List> component accepting data, height, itemHeight, and a render-prop children function per item
  • Automatic real-height measurement via ResizeObserver for variable-height rows, correcting the virtual offset as items are measured
  • A custom ScrollBar with drag-to-scroll and both vertical and horizontal scrolling support (scrollWidth prop)
  • Touch and mobile scroll handling (useMobileTouchMove) plus wheel-based frame scrolling (useFrameWheel) for smooth cross-device behavior
  • An escape hatch (virtual={false}) to disable windowing and render a plain scrollable list when data sets are small

Common Use Cases

  • Rendering dropdown/select option lists with thousands of entries without frame drops
  • Building custom data tables or trees that need to virtualize rows or nodes
  • Powering infinite-scroll feeds where only a slice of items should exist in the DOM at once
  • Replacing ad-hoc virtualization logic in a design system with a maintained, tested primitive
  • Adding horizontal virtual scrolling to wide tables via the scrollWidth prop

Under The Hood

Architecture - List.tsx (the ~685-line core) composes several focused hooks — useHeights for per-item height caching, useDiffItem to compute added/removed items across renders, useFrameWheel/useMobileTouchMove for input handling, and useScrollTo for imperative scroll APIs exposed via ListRef — around a Filler component that renders a spacer sized to the full virtual content height with the visible slice absolutely positioned inside it. ScrollBar.tsx implements a separate draggable thumb overlay rather than relying on native scrollbars, giving consistent styling and drag behavior across browsers. Tech Stack - TypeScript targeting React 18+/19 as peer dependencies, built with father (the rc-component build tool) into ES and CJS output, using @rc-component/resize-observer for height measurement and @rc-component/util’s useEvent/useLayoutEffect for stable callback refs; docs are built with dumi. Code Quality - A tests/ directory covers list rendering, scroll behavior (including a Firefox-specific scroll test), props, touch interaction, and utility functions via rc-test/@testing-library/react, with ESLint (flat config) and Prettier enforced through Husky pre-commit hooks — a notably more mature testing setup than many rc-component siblings. API Design - The single <List> component with data/itemHeight/itemKey/render-prop children mirrors plain array .map() ergonomics, keeping adoption low-friction, while advanced behavior (horizontal scroll, imperative scrollTo, custom scrollbar styling) is opt-in via additional typed props rather than required configuration.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search