react-virtual vs react-virtualized vs react-window
大規模リストの仮想化とレンダリング戦略
react-virtualreact-virtualizedreact-window類似パッケージ:

大規模リストの仮想化とレンダリング戦略

react-virtualizedreact-windowreact-virtual は、React アプリケーションで数千行を超えるリストやテーブルをパフォーマンス低下なく表示するためのライブラリです。これらは「ウィンドウ化」(仮想化)技術を用いて、現在画面に見えているアイテムだけをレンダリングし、スクロールに応じて内容を入れ替える仕組みを持っています。react-virtualized はかつての標準でしたが、現在は react-window への移行が推奨されています。react-virtual はフックベースのヘッドレスアプローチを提供しますが、現在は @tanstack/react-virtual へ統合されています。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
react-virtual06,809158 kB105-MIT
react-virtualized027,0682.24 MB01年前MIT
react-window017,143209 kB12ヶ月前MIT

大規模リストの仮想化:react-virtualized vs react-window vs react-virtual

React で数千件以上のデータを表示する際、すべてを一度に描画するとブラウザが重くなり操作不能になります。これを防ぐため、見える部分だけを描画する「仮想化」技術が必要です。react-virtualizedreact-windowreact-virtual はこの課題を解決する代表的なライブラリですが、設計思想と使い方が大きく異なります。

🏗️ 設計思想:コンポーネント提供 vs ヘッドレス

react-virtualized は、リストやグリッドのための完成されたコンポーネントを提供します。

  • 用意された <List><Grid> を使います。
  • 内部構造が隠蔽されており、カスタマイズには制限があります。
// react-virtualized: 完成されたコンポーネントを使用
import { List } from 'react-virtualized';

<List
  width={600}
  height={400}
  rowCount={1000}
  rowRenderer={({ index, style }) => (
    <div style={style}>Row {index}</div>
  )}
/>

react-window もコンポーネントを提供しますが、より軽量でシンプルです。

  • react-virtualized の問題点を解消するために作られました。
  • API が整理されており、不要な機能が削ぎ落とされています。
// react-window: 軽量なコンポーネントを使用
import { FixedSizeList } from 'react-window';

<FixedSizeList
  width={600}
  height={400}
  itemCount={1000}
  itemSize={35}
>
  {({ index, style }) => (
    <div style={style}>Row {index}</div>
  )}
</FixedSizeList>

react-virtual は、UI を提供しない「ヘッドレス」なフックです。

  • 計測と計算だけを行い、描画は開発者が任されます。
  • 自由度高いですが、自分で DOM 構造を作る必要があります。
  • ※ 注意:このパッケージは非推奨で、現在は @tanstack/react-virtual が正式です。
// react-virtual: フックで計測だけ行う(非推奨パッケージ)
import { useVirtual } from 'react-virtual';

const virtual = useVirtual({
  size: 1000,
  parentRef,
  estimateSize: () => 35,
});

return (
  <div ref={parentRef}>
    <div style={{ height: virtual.getTotalSize() }}>
      {virtual.virtualItems.map(item => (
        <div key={item.key} style={{ transform: `translateY(${item.start}px)` }}>
          Row {item.index}
        </div>
      ))}
    </div>
  </div>
);

📦 導入と設定の手間

ライブラリの選び方は、プロジェクトの柔軟性要件によります。

  • react-virtualized は設定項目が多く、初期コストが高いです。古い設計のため、現代の React 機能(例:Hooks)との相性が良くありません。
  • react-window は必要十分な機能に絞られており、導入が簡単です。標準的なユースケースならこれで十分です。
  • react-virtual は DOM 構造を自分で組むため、自由なレイアウトが可能です。しかし、その分手間がかかります。

💡 ヒント:react-virtual パッケージは現在メンテナンスされていません。同等の機能が必要な場合は @tanstack/react-virtual を使用してください。

📏 可変サイズアイテムの扱い

アイテムの高さが一定でない場合(例:チャットログ、コメント欄)、各ライブラリの対応は以下の通りです。

react-virtualizedCellMeasurer と言うコンポーネントで計測します。

  • 一度レンダリングしてからサイズを測るため、初期表示に遅延が出ることがあります。
// react-virtualized: CellMeasurer で計測
<CellMeasurerCache defaultHeight={100}>
  <List
    rowRenderer={({ index, style, parent }) => (
      <CellMeasurer key={index} cache={cache} parent={parent} index={index}>
        {({ measure, height }) => (
          <div style={style} onLoad={measure}>
            Content {index}
          </div>
        )}
      </CellMeasurer>
    )}
  />
</CellMeasurerCache>

react-windowVariableSizeList コンポーネントを使います。

  • 開発者がサイズを管理し、変更時に resetAfterIndex で通知します。
// react-window: 可変サイズリスト
import { VariableSizeList } from 'react-window';

<VariableSizeList
  itemCount={1000}
  itemSize={index => heights[index]}
  onItemsRendered={({ visibleStopIndex }) => {
    // 必要に応じてサイズ更新を通知
  }}
>
  {({ index, style }) => (
    <div style={style}>Row {index}</div>
  )}
</VariableSizeList>

react-virtual はフック内でサイズを推定し、必要に応じて更新します。

  • 計測ロジックを自由に書けるため、複雑な条件にも対応可能です。
// react-virtual: 推定サイズと計測
const virtual = useVirtual({
  size: rows.length,
  parentRef,
  estimateSize: () => 50, // 推定値
  measureSize: (el) => el.getBoundingClientRect().height, // 実測ロジック
});

⚠️ 保守性と将来性

この点が最も重要な選定基準になります。

react-virtualized は事実上のレガシーです。

  • 作者が react-window への移行を公式に推奨しています。
  • バグ修正は行われますが、新機能は追加されません。
  • 新規プロジェクトでの使用は避けるべきです。

react-window は安定しており、広く使われています。

  • 作者によって積極的にメンテナンスされています。
  • React の最新バージョンとの互換性も保たれています。
  • 標準的なリスト表示なら、これが最も安全な選択です。

react-virtual はパッケージ名として非推奨です。

  • 機能は @tanstack/react-virtual へ引き継がれました。
  • フックベースの設計は現代的ですが、パッケージ名に注意が必要です。
  • -headless なアプローチが必要な場合のみ、新しい方を選択します。

📊 比較まとめ

特徴react-virtualizedreact-windowreact-virtual
提供形態完成コンポーネント軽量コンポーネントヘッドレスフック
保守状況レガシー(移行推奨)安定・維持中非推奨(TanStack へ)
API 難易度高い(複雑)低い(シンプル)中(自作要素あり)
柔軟性低い高い
推奨度❌ 新規採用非推奨⭕ 標準的な選択⚠️ パッケージ名に注意

💡 最終的な推奨

react-window を第一選択としてください。

  • ほとんどのリスト表示ニーズを満たします。
  • 作者が保証しており、コミュニティも厚いです。
  • 実装がシンプルで、バグの入り込む隙が少ないです。

@tanstack/react-virtualreact-virtual の後継)を検討するのは以下の場合です。

  • React 以外のフレームワークともロジックを共有したい。
  • 独自の DOM 構造で仮想化を実装する必要がある。
  • 極めて特殊なスクロール挙動が求められる。

react-virtualized は使わないでください。

  • 既存プロジェクトの維持以外にメリットはありません。
  • 新規開発では技術的負債になります。

仮想化ライブラリの選択は、パフォーマンスと保守性のバランスです。標準的な道を選ぶなら react-window、特殊な制御が必要なら @tanstack/react-virtual、これが現代の正しい選び方です。

選び方: react-virtual vs react-virtualized vs react-window

  • react-virtual:

    このパッケージ名は非推奨であり、代わりに @tanstack/react-virtual を使用すべきです。フックを使ってレンダリングロジックを完全に制御したい場合に適しています。フレームワークに依存しないコアロジックが必要なら、新しい方のパッケージを検討してください。

  • react-virtualized:

    既存のレガシープロジェクトを維持する場合を除き、新しいプロジェクトでの使用は推奨しません。作者自身によって react-window への移行が勧められており、バンドルサイズが大きく API も複雑です。維持コストがかかるため、新規採用は避けるべきです。

  • react-window:

    React コンポーネントとして手軽に仮想化リストを実装したい場合に最適です。作者が react-virtualized の後継として設計しており、API がシンプルで学習コストが低いです。標準的なリストやグリッド表示であれば、これが第一選択肢になります。

react-virtual のREADME

Table of Contents generated with DocToc

React Virtual Header

Hooks for virtualizing scrollable elements in React

#TanStack Join the community on Spectrum

Enjoy this library? Try the entire TanStack! React Query, React Table, React Charts, React Form

Visit react-virtual.tanstack.com for docs, guides, API and more!

Quick Features

  • Row, Column, and Grid virtualization
  • One single headless hook
  • Fixed, variable and dynamic measurement modes
  • Imperative scrollTo control for offset, indices and alignment
  • Custom scrolling function support (eg. smooth scroll)