2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】material-react-table v2のフィルター作成方法について

Posted at

おはこんばんにちは、フリーランスエンジニアのせなです。
最近ReactでWebアプリを開発する際にMaterial React Tableのフィルターを作成する方法が分からなかったので備忘録も兼ねて紹介したいと思います。

プロジェクトのソースコードはGitHubにあげています。
詳細が気になる方はそちらも参照してください。

事前準備

今回はYarnを使ってプロジェクトを作成します。
その他の方法でプロジェクトを作成する場合は適宜読み替えてください。

cd /path/to/your/project
yarn create react-app app --template typescript
cd app
yarn add material-react-table @mui/material @mui/x-date-pickers @mui/icons-material @emotion/react @emotion/styled dayjs
# ↓はフィルターとは関係ありません。
# プロジェクト作成時に必要だった最低限のライブラリです。
yarn add react-router-dom tailwindcss

ディレクトリ構成

今回は以下のディレクトリ構成で作成します。
今回のフィルター説明とは直接関係はないので、読み飛ばしても大丈夫です。

app
├── src
│   ├── App.tsx - メインコンポーネント
│   ├── providers
│   │   ├── app.tsx - プロバイダー
│   ├── routes
│   │   ├── index.tsx - ルーティング
│   ├── features
│   │   ├── table
│   │   │   ├── components
│   │   │   │   ├── UserTable.tsx - テーブルコンポーネント
│   │   │   │   ├── CustomDatePicker.tsx - 日付ピッカーコンポーネント
│   │   │   ├── filters
│   │   │   │   ├── dateFilter.ts - 日付フィルター(今回の本題)
│   │   │   ├── routes
│   │   │   │   ├── index.ts - ルーティング
│   │   │   │   ├── TableRoute.tsx - テーブルのルーティング

フィルターの作成方法

ここからが本題です。
フィルターを作成するためには、MRT_FilterFnを使用します。

以下は、日付の範囲を指定するフィルターの例です。

import { MRT_FilterFn } from "material-react-table";

const dateFilter: MRT_FilterFn<any> = (
  row,
  columnId,
  filterValue,
) => {
  const rowValueDate: Date = row.getValue(columnId);

  const filterStartDate = filterValue[0];
  const filterEndDate = filterValue[2];

  if (filterStartDate && filterEndDate) {
    // 期間の開始・終了が指定されている場合
    const isValid = rowValueDate >= filterStartDate && rowValueDate <= filterEndDate;
    return isValid;
  } else if (filterStartDate && !filterEndDate) {
    // 期間の開始が指定されている場合
    const isValid = rowValueDate >= filterStartDate;
    return isValid;
  } else if (!filterStartDate && filterEndDate) {
    // 期間の終了が指定されている場合
    const isValid = rowValueDate <= filterEndDate;
    return isValid;
  } else {
    // 期間が指定されていない場合
    return true;
  }
}

export default dateFilter;

このフィルターを使用するためには、useMaterialReactTablefilterFnsに登録する必要があります。
以下は、useMaterialReactTableのサンプルコードです。

const table = useMaterialReactTable({
    columns,
    data,
    initialState: {
      showColumnFilters: true,
      showGlobalFilter: true,
    },
    enableColumnResizing: true, // 列幅変更
    enableColumnFilters: true, // 列フィルター
    enableRowSelection: false, // 行のチェックボックス
    enableFilterMatchHighlighting: false, // フィルターのハイライト
    enableColumnFilterModes: true, // 列フィルターモード
    enableColumnDragging: false, // 列ドラッグ
    enableColumnOrdering: false, // 列並び替え
    enableColumnPinning: true, // 列固定
    enableColumnActions: false, // 列アクション
    filterFns: {
      // 日付のフィルター処理
      'dateFilter': dateFilter as FilterFn<any>,
    },
    state: {
      columnFilters,
      globalFilter,
      isLoading
    },
    onColumnFiltersChange: setColumnFilters,
    onGlobalFilterChange: setGlobalFilter,
});

そして、fileterFnsに登録したdateFilterを使用するカラムのfilterFnに指定します。

{
    accessorKey: 'birthday',
    header: '誕生日',
    minSize: 75,
    maxSize: 400,
    size: 125,
    enableSorting: false, // ソートを無効
    enableColumnActions: false, // : のカラムアクションを無効
    enableColumnFilter: false, // カラムのフィルター表示を無効
    filterFn: 'dateFilter',
},

これで、誕生日の範囲を指定してフィルターを行うことができるようになっているかと思います。

以下のような、日付を選択するコンポーネントを作成して、フィルターを行うことができます。

  const header = table.getHeaderGroups()[0]
  const birthdayColumn = header.headers[2].column  // 誕生日カラム

  const [startDateFilterValue, setStartDateFilterValue] = useState<string | null>(dayjs().year(2024).month(0).date(1).format("YYYY/MM/DD"));
  const [endDateFilterValue, setEndDateFilterValue] = useState<string | null>(dayjs().year(2024).month(1).date(-1).format("YYYY/MM/DD"));

  return (
    <div className="flex flex-col justify-center items-center w-full min-h-screen">
      <CustomDatePicker
        value={dayjs(startDateFilterValue).format("YYYY-MM-DD") ?? ''}
        onChange={(value: string) => {
          birthdayColumn.setFilterValue((old: [string, string, string, string]) => [value, old?.[1], old?.[2], old?.[3]])
          setStartDateFilterValue(value);
        }}
        label="開始日"
        className="w-40"
      />
      <CustomDatePicker
        value={dayjs(endDateFilterValue).format("YYYY-MM-DD") ?? ''}
        onChange={(value: string) => {
          birthdayColumn.setFilterValue((old: [string, string, string, string]) => [old?.[0], old?.[1], value, old?.[3]])
          setEndDateFilterValue(value);
        }}
        label="終了日"
        className="w-40"
      />
      <div className="w-5/6">
        <MaterialReactTable table={table} />
      </div>
    </div>
  );

実際に動作させると次のようなイメージとなります。
datefilter-describe.gif

以上で、MRTのテーブルにフィルターを作成する方法を紹介しました。

まとめ

今回説明した方法は日付をフィルターする方法ですが、他のフィルターも同様の方法で作成することができます。
例えば日時(datetime)のフィルターについては以下にサンプルコードをあげていますので、参考にしてみて下さい。
datetimeFilter.ts

他にもっと良い方法があるよ! って方がいればコメントで教えてもらえると嬉しいです!

ではでは〜

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?