旧ブログ(ISSEN)から移行しました

React Virtuosoの4つのコンポーネント紹介

React Virtuosoの4つのコンポーネント紹介

塩見直樹
塩見直樹5分で読めます

はじめに

こんにちは、株式会社TOKOSのナオキです!
前回Reactのライブラリである「React Virtuoso」について紹介をしました。

【React】React Virtuosoライブラリの紹介とReact Windowライブラリとの比較

この記事ではReactのライブラリであるReact Virtuosoについての紹介と、ReactのライブラリであるReact Windowとの違いについて解説しています。

blog.to-ko-s.com

今回はその「React Virtuoso」のコンポーネントを使用した多様なリストの作成方法を紹介します。前回の記事でReact Virtuosoについての説明をしているのでこの記事では細かな説明は省かせてもらいます。
ぜひ参考にしてもらえると嬉しいです!

概要

「React Virtuoso」はReactライブラリで、沢山のDOM要素をもつリストやテーブルを仮想化して表示するためのライブラリです。画面の表示領域に入っている要素のみをレンダリングさせるのでパフォーマンス向上に適しています!
React Virtuosoには4つのコンポーネント(Virtuoso、Grouped Virtuoso、Table Virtuoso、Virtuoso Grid)があります。
それぞれを使用したリスト作成の紹介をします。

対象読者

  • React初学者の方
  • React Virtuosoを使用してパフォーマンス改善をしようとしている方

開発環境

  • react: "18.2.0"
  • react-virtuoso: "^4.7.4"
  • tailwindcss: "^3.3.3"
  • typescript: "^5.3.3"

今回はTailwindcssを使用しています!

Virtuosoコンポーネント

React Virtuosoライブラリのコンポーネントで一番基本的なコンポーネントです。

Virtuosoを使用したサンプルリスト

コード

List.tsx
import { Virtuoso } from "react-virtuoso"
 
export default function List() {
  return (
    <Virtuoso
      style={{ height: 500, width: 400 }} /* リストの表示領域を指定 */
      totalCount={1000} /* リスト要素の総数を指定 */
      itemContent={(index) => (
        <div className="flex flex-col items-center justify-center border p-3">
          {/* 要素のスタイルを指定 */}
          <p>user {index}</p>
        </div>
      )}
    />
  )
}

表示させたい領域をwidthheightで指定しています。
totalCountでは表示させたい要素の数を指定します。

Grouped Virtuosoコンポーネント

グループ形式のデータを表示させるためのコンポーネントです。

Grouped Virtuosoを使用したサンプルリスト

コード

List.tsx
import React, { useMemo } from "react"
import { GroupedVirtuoso } from "react-virtuoso"
 
export default function List() {
  const groupCounts = useMemo(() => {
    return Array(1000).fill(
      10,
    ) /* グループの総数と1つのグループに含まれる要素を指定 */
  }, [])
 
  return (
    <GroupedVirtuoso
      style={{
        /* リストの表示領域を指定 */ height: 600,
        width: 400,
      }}
      groupCounts={groupCounts}
      groupContent={(index: number) => {
        /* 各グループのスタイルやコンテンツを指定 */
        return <div className="bg-gray-500 p-3 text-white">Group {index}</div>
      }}
      itemContent={(
        index: number,
        groupIndex: number /* 各要素のスタイルやコンテンツを指定 */,
      ) => (
        <div className="border p-3">
          {index} (group {groupIndex})
        </div>
      )}
    />
  )
}

groupCountsでグループの総数と1つのグループに含まれる要素数を指定しています。
Array(1000)でグループの総数を1000個に指定し、fill(10)で1つのグループに含まれる要素を10個に指定しています。
リストのヘッダー部分のスタイルをgroupContentで指定しています。

Table Virtuosoコンポーネント

テーブル形式のデータを表示させるためのコンポーネントです。

Table Virtuosoを使用したサンプルリスト

コード

List.tsx
import React, { useMemo } from "react"
import { TableVirtuoso } from "react-virtuoso"
 
type User = {
  /* User型を定義 */
  name: string
  age: number
  description: string
  gender: string
}
 
export default function List() {
  const users: User[] = useMemo(() => {
    return Array.from({ length: 1000 }, (_, index) => ({
      /* テーブルに表示する1000個のユーザーデータを作成 */
      name: `User ${index}`,
      age: 20,
      description: `Description for user ${index}`,
      gender:
        index % 2 === 0
          ? "男性"
          : "女性" /* indexが偶数なら男性、奇数なら女性と表示させる */,
    }))
  }, [])
 
  return (
    <TableVirtuoso
      style={{ height: 590, width: 600 }} /* リストの表示領域を指定 */
      data={users} /* テーブルに表示されるデータを指定 */
      components={{
        Table: ({ style, ...props }) => (
          <table
            {...props}
            style={{ ...style, width: "100%" }}
          /> /* テーブル全体のスタイルを指定 */
        ),
      }}
      fixedHeaderContent={() => (
        /* 固定されたリストのヘッダーのスタイルを指定 */
        <tr>
          <th className="border bg-gray-500 p-3 text-white">Name</th>
          <th className="border bg-gray-500 p-3 text-white">Gender</th>
          <th className="border bg-gray-500 p-3 text-white">Age</th>
          <th className="border bg-gray-500 p-3 text-white">Description</th>
        </tr>
      )}
      itemContent={(_, user /* リスト要素のスタイルを指定 */) => (
        <>
          <td className="border p-3 text-center">{user.name}</td>
          <td className="border p-3 text-center">{user.gender}</td>
          <td className="border p-3 text-center">{user.age}</td>
          <td className="border p-3 text-center">{user.description}</td>
        </>
      )}
    />
  )
}

dataでテーブルに表示させるデータを取得しています。
リストの上部に固定されるヘッダーのスタイルをfixedHeaderContentで指定し、リスト要素のスタイルをitemContentで指定します!

Virtuoso Gridコンポーネント

グリッド形式のデータを表示するためのコンポーネントです。

Virtuoso Gridを使用したサンプルリスト

コード

List.tsx
import React from "react"
import { VirtuosoGrid } from "react-virtuoso"
 
export default function List() {
  return (
    <>
      <VirtuosoGrid
        style={{ height: 500, width: 600 }} /* リストの表示領域を指定 */
        listClassName="grid grid-cols-3 gap-3 border" /* リストの形式をグリッドに指定 */
        itemClassName="p-3 border text-center" /* リスト要素のスタイルを指定 */
        totalCount={1000} /* リスト要素の総数を指定 */
        itemContent={(index: number) => (
          <div>
            <p>user {index}</p>
          </div>
        )}
      />
    </>
  )
}

listClassNameでリストの形式をグリッドに指定しています。
リスト要素のスタイルはitemClassNameで指定しています!

さいごに

今回はReact VirtuosoのコンポーネントであるVirtuoso, Grouped Virtuoso, Table Virtuoso, Virtuoso Gridそれぞれのリストの紹介をしました。
コードを見てもらえると分かる通りとてもシンプルで簡単に実装ができます!
ぜひリスト作成をするときに使ってみてください!

この記事を書いた人

塩見直樹
塩見直樹

TOKOSのバックエンドエンジニア。パフォーマンス最適化と可読性の向上を目指しています。アニメ好きで、特にHUNTER×HUNTERが好きです。