モーダル表示のパフォーマンスをReact-Virtuosoで改善した話

2023/06/10に公開

解決したい問題

モーダル表示が低スペックなスマホだと数秒かかるという問題がありました。
モーダルでは数百件のチェックボックスをリスト表示させており、inputの生成に時間がかかっていることが原因でした。

React-Windowを導入してみる

初期レンダリングのコストを解消するため、React-Windowを導入してみました。
結果として、パフォーマンス的には問題は解消したのですが、React-Windowには高さが可変のリスト表示が困難という弱点があり、対応中のプロダクトへの適用は困難でした。

React-Windowに関しては、以下のサイトが分かりやすいと思います。
https://zenn.dev/dove/articles/4649c8e2dc3cd8

上記サイトにも記載がありましたが、無限ローディングの技術での解決を試みることにしました。

React-Virtuosoの導入

導入は非常に簡単です。

     import {Virtuoso} from 'react-virtuoso'
     
      <Virtuoso
        totalCount={elements.length}
        itemContent={(index): JSX.Element => (
          <div className={styles.list}>{elements[index]}</div>
        )}
      />

elementsは、React.JSX.Element[]でCheckboxの配列が実態です。
※公式ドキュメントも参照
https://virtuoso.dev/hello/#list-with-totalcount

パフォーマンス的には最大4,5秒かかっていたものが、一瞬で表示されるようになりました。
React-Windowのように高さを指定する必要がないため、長いラベルを折り返した場合などに表示崩れが起きることもなく表示されています。

結論

長いリストのパフォーマンス改善では、React-Virtuosoのような無限ローディングの技術も活用できるということを学びました。

テストに関して

React-Virtuosoを導入すると、testing-libraryのテストが失敗するようになります。
こちらの解決も非常に簡単でVirtuosoMockContextをラップさせてあげれば解消します。
https://virtuoso.dev/mocking-in-tests/

コードの修正としては、
最初の要素を取得する際に、getBy〜で取得できていたものをfindBy〜に置換する必要があります。

Discussion