【React Table v7 → v8】【TypeScript 】アップデートの勘所
こんにちはフロントエンドエンジニアの茶木です。
前回まで React Table
を v7 で、TypeScript で型付けしながら書いていたのですが、年も明けたことですし、 v7 から v8 に アップデートしていきます。
ファイル構成
pages/index.ts
で components/Table/index.ts
の Table コンポーネントを呼び出す想定です。
基本の構成は v7 と変えていませんが、1ファイル1コンポーネントになるように書き直しています。
├ components/
│ └ Table/
│ ├ Header/
│ │ ├ index.tsx
│ │ ├ Row.tsx
│ │ └ Cell.tsx
│ ├ Body/
│ │ ├ index.tsx
│ │ ├ Row.tsx
│ │ └ Cell.tsx
│ ├ Cell/
│ │ └ DateCell.tsx
│ ├ index.tsx
│ └ TableContent.tsx
└ pages/
└ index.ts
Columnsの定義
大きな変更のある箇所について述べていきます。
まず、Columnsの定義ですが、createColumnHelper
という関数が使えるようになりました。v7 では accessor: "id" as const
といったように書いていた箇所が読みやすくなります。
import { createColumnHelper } from "@tanstack/react-table";
const columnHelper = createColumnHelper<MatchResult>();
const columns = [
columnHelper.accessor("id", {
header: "id",
}),
columnHelper.accessor("updatedTimestamp", {
header: "更新日",
cell: DateCell,
}),
];
また、ここで columns の型は、 v7では Column<R>[]
だったものが、 ColumnDef<R, D>[]
に変わります。R
は各行が持つ列の形式で、表示するテーブルによって変えるためにジェネリクスの形式をとっています。こちらは v7 の方と変わりません。
interface RowSample{
id: string;
updatedTimestamp: number;
}
そして D
は、各列の値の型の union type になる模様です。 (後述)
useReactTable
v7 で useTable
だったものは v8 では useReactTable
に変わっています。
data は R型を持つ rows で React Table で管理する値になります。columns は先程の columns定義になります。v8 では、さらに getCoreRowModel
というのを渡します。getCoreRowModel()
はライブラリから提供されています。
const table = useReactTable<R>({
data: rows,
columns,
getCoreRowModel: getCoreRowModel(),
});
行の描画
v7 では行の生成に table.rows
と table.prepareRow
を使っていましたが、 v8 では、table.getRowModel().rows
を使います。rows.map
で各行を描画します。
<MuiTableBody>
{table.getRowModel().rows.map((row) => (
<TableRow key={row.id} row={row} />
))}
</MuiTableBody>
列の描画
v7 では列の描画に row.cells
を使いましたが、 v8 では、 row.getVisibleCells()
を使います。row.getVisibleCells().map
で各行を描画します。
<MuiTableRow>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id} cell={cell} />
))}
</MuiTableRow>
セルの描画
v7 では cell.render("Cell")
を使いましたが、 v8 では、 flexRender()
を使います。コードは下記のとおりです。
<MuiTableCell>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</MuiTableCell>
個別の装飾セル
columns
にわたす Cellコンポーネントの説明をします。v7 では props.value
で値を取得していましたが、v8 では props.getValue()
を使用します。
例では、timestamp を年月日に加工しています。
<>
{format(new Date(props.getValue()), "yyyy-MM-dd")}
</>
テーブルヘッダー
端折って説明します。
table.getHeaderGroups()
から headerGroups
生成します。headerGroups
配列の要素 headerGroup
、 headerGroup
配列の要素 header
が TableBody
のセルに相当し、こちらも flexRender
を使って描画します。
TypeScript ハマりポイント
以上が v7 から v8 への移植の基本的な説明でした。
1点ハマりポイントがあり、Columns定義を Tableコンポーネントにわたす際の、Tableコンポーネントの props の型定義をどうするか、です。
ColumnDef<R, D>[]
の形をとると述べました。D
は、各列の値の型の union type になるので、(一手間かければ)R
からうまく抽出できそうなのですが、data
に含まれる行のすべてを使わない場合、columns と不一致になってしまうので、厳密性と利便性を天秤にかけて D
は any
を設定しています。研究の余地ありです。
columns: ColumnDef<R, any>[];
おわりに
v7 から v8 に代わり、値の取得の箇所がメソッドに大きく変わっている点を注意すれば、比較的難しくなく移管できると思います。
Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています
弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?
もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!
求人応募してみる!