🧢

無限スクロールにはReact-Virtuosoが良さそう🧩

2023/04/19に公開

結論

タイトルにもありますが無限スクロールの UI 実装にはreact-virtuosoが良さそう

経緯

テーブルとグリッドを切り替える事ができる一覧ビューの UI をページネーションから無限スクロールに変更する必要があった。また UI 実装は基本的に MUI を活用することが前提です。

  • ページネーション(現状の UI)

    • Datagrid(free plan)とPaginationを使いテーブルの UI を実装(この記事では DataGrid の詳細については言及しません)
    • 1 ページ(1 テーブル)に 20 件ずつ表示
    • mui のdatagrid サンプルの Footer がbasic-paginationに置き換わるイメージ
  • 無限スクロール(変更後の UI)

    • 1 テーブル(1 ページ)に対してテーブルの最下部のスクロール毎に 20 件ずつアイテムが増加する

現在テーブルに使用しているコンポーネント(Datagrid-free plan)で次の問題が発生した。

DataGrid Pro にアップグレードするか、それ以外か

まず、100 件以上にデータ表示対応するためには、以下 2 つのどちらかを採用するか検討する必要がある。

この 2 つの案で発生しそうな作業と懸念点をざっと書いてみる。

1.DataGrid を ProPlan にアップグレードする

  • free → Pro の移行対応
  • infinite-loadingを活用して無限スクロールの実装
  • API レスポンスの現在表示されているデータにマージする
    • api リクエストするパラメータの調整
    • 状態管理
  • グリッドビューで結局無限スクロール対応が必要になる
  • MUI Pro Plan は 1 年間で 1 デベロッパーにつき$180 の支払いが必要

2.DataGrid を廃止し、無限スクロールライブラリを活用しテーブルをリプレースする

  • DataGrid からBasic-Tableにリプレース
  • ローディング
  • 無限スクロールライブラリとリプレースされた MUI の Table コンポーネントを繋ぎ合わせる
    • 要素の最下部にスクロールしたかどうかを返す
    • パフォーマンス最適化
      • スクロール毎にイベントを発火させない(遅延処理)
    • 新しくデータを読み込んだ場合のスクロール位置の調整
      • ローディング表示も必要
    • ページの状態を保持する
      • 一覧から詳細画面に行き、一覧に戻った時に直前の位置を取得する
  • 無限スクロールライブラリの活用でグリッドビューの対応も出来る
  • API レスポンスの現在表示されているデータにマージする(1 と同様)
    • api リクエストするパラメータの調整
    • 状態管理

1 について

  • テーブルの無限スクロール対応は容易
  • テーブルの無限スクロールのためだけに 1developer につき$180 払う必要がある
  • グリッドビューで無限スクロールの実装がどちらにしろ必要になりそう

2 について

  • テーブル、グリッドビューどちらも同様の手順で対応出来そう(共通化できそう)
  • テーブルのリプレースに時間がかかる

結果、無限スクロールのためだけに課金する必要がないと判断したのと、グリッドビューで無限スクロールの判定を実装することが必要なので、DataGrid Pro にアップデートするのはやめました。

無限スクロールライブラリ比較

次にどの無限スクロールライブラリを活用するかの比較を行う。
10 Best React Infinite Scroll Libraries in 2023から 3 つピックアップして比較してみた。

選んだ基準は以下 3 点です

  • 1 年以内にメンテされている
  • MUI との相性が良さそうか
  • 無限スクロールのサンプルが用意されている
name 無限スクロール例 備考
react-virtualized https://bvaughn.github.io/react-virtualized/#/components/InfiniteLoader - mui で使用しているテーブルを virtualized から virtuoso に移行にした模様なので少し古そう
- sample 実装では class コンポーネントで記述されているため少し読みづらい
react-virtuoso https://virtuoso.dev/endless-scrolling/ - endReached(最下部判定)や initialTopMostItemIndex(初期表示のスクロール位置指定)などの便利そうなプロパティが用意されている
- typescript with hooks で書かれている
TanStack Table https://tanstack.com/table/v8/docs/examples/react/virtualized-infinite-scrolling - 無限スクロールを自前で実装する必要がある
- (例はあるがよく見ると virtuoso の endReached のようなものが用意されていなかった)

終わりに

  • そもそも最初に無限スクロールに置き換わるかもしれないことを考慮できていれば UI をまるごとリプレースせずに済んだ
  • ブラウザバックした場合のページネーションの状態管理やスクロールの位置管理など他にも記事書けそう
  • 実際に react-virtuoso を使ってみての感想や使い勝手の良さを後に書こうと思います

Discussion