【React Table】セルの装飾と加工を TypeScript で記述する


こんにちはフロントエンドエンジニアの茶木です。
最近は学習用の Next.js の ローカルの SandBox を育てています。

前回記事で、React Table の基本について TypeScript で書きました。今回はセルの表示の加工や装飾について書いていきます。

セルの加工

まず、更新日を例に話をします。

前回記事 に則った呼び出し側です

const columns = [
  {
    Header: "id",
    accessor: "id" as const,
  },
  {
    Header: "更新日",
    accessor: "updatedTimestamp" as const,
  },
];

export default function Members() {
  const data = useMembers();
  if( !data ) return <p>Loading...</p>
  return <Table<MembersResult> rows={data.rows} columns={columns} />
};

更新日などの timestamp を UNIX時間で記録しDBから取得するとき、年月日や時間に変換するフォーマットはフロントエンドで行うのは一般的かと思います。

現状は Cell の値をそのまま表示しているので、UNIX時間が表示されています。これを年月日に変換します。

更新日はUNIX時間ではなく年月日で表示されてほしい

  {
    Header: "更新日",
    accessor: "updatedTimestamp" as const,
    Cell: DateCell,
  },

columnsHeader: "更新日" の項目に Cell: DateCell を設定します。
DateCell は自作のコンポーネントです。

import { format } from "date-fns";
import { ReactElement } from "react";
import { CellProps } from "react-table";

import { BaseRow } from "../../../difinitions/table";

type Props<T extends BaseRow> = CellProps<T, number>;

export const DateCell = <T extends BaseRow>({
  value,
}: Props<T>): ReactElement => {
  return <>{format(new Date(value), "yyyy-MM-dd")}</>;
};

props のメンバーには様々な値が含まれますが、今回解説するのは valuerow です。そして今回使用するのは value だけです。

  • value: セルで表示される値(columnsのCellを指定しない場合に生の状態で表示される値)
  • row: このセルを含む行。他のセルの値を参照するケースで使用できる。

今回はこの value を年月日に変換して表示します。

yyyy-MM-dd の形式で表示されました

CellProps

Typescript の解説です

CellProps は react-table から提供される Cellの props を規定するためのものです。

type Props<T extends BaseRow> = CellProps<T, number>;

CellProps<Row, T> の形式で指定し、row の型は ROW, value の型は T とみなされます。

export type BaseRow = {
  id: string;
} & Record<string, unknown>;

また、CellProps に渡している <T extends BaseRow>BaseRow前回記事 で定義したTable の共通部分です。

セルの装飾

装飾についても少し触れておきます。スタイリングの方法は様々ですが何を選択しても value を ReactElement で囲む形で行うことになると思います。

今回は、MUI でスタイルを付与しています。行ごとに違ったスタイルをあてることもできます。今回は更新日時のうち、直近の更新のあったもの(本日の日付のもの)を赤色にしてみています。

import { format, isToday } from "date-fns";
import { ReactElement } from "react";
import { styled } from "@mui/material/styles";
import { CellProps } from "react-table";

import { BaseRow } from "../../../difinitions/table";

const Cell = styled("div")({
  fontWeight: "bold",
});

type Props<T extends BaseRow> = CellProps<T, number>;

export const DateCell = <T extends BaseRow>({
  value,
}: Props<T>): ReactElement => {
  const date = new Date(value);
  return (
    <Cell sx={{ color: isToday(date) ? "red" : undefined }}>
      {format(date, "yyyy-MM-dd")}
    </Cell>
  );
};

出し分けができました

おわりに

セルの加工および装飾は Cell で行います。基本的には value フォーマットの種類だけ Cellを用意するのがわかりやすいと思います。

今回紹介した日時のほかにも、たとえば

  • リンク(URLに変える)
  • 金額(カンマ区切りや通貨マーク)
  • 列挙型のステータスを文字列として表示(未着手・作業中・完了など)

といったフォーマットが想定できます。

また、アドバンスの用法として、CellProps に含まれる row で同一行の他セルの値を参照できます。
row を参照するケースは

  • 未入力項目がある場合にセルにメッセージを表示する
  • 行のIdを取得して、データの変更をAPIで送信するsubmit ボタンを表示する

といったものです。

特にデータの変更をAPIで送信するケースは、セルの動的な編集に必要ですので。次回以降のブログで解説したいと思います。

Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています

弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!

投稿者 Chaki Hironori

webライターもやってるフロントエンドエンジニアです。Reactは自信があります。またデザイン畑の出身で、気持ちのいいアニメーションやインタラクティブな表現は丁寧に手掛けます。好きなものは中南米の遺跡で、スペイン語が少しできます。