React + Material-UIの画面にmaterial-tableを導入してみた

2020.08.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部の若槻です。

Reactで使えるMaterial-UIをベースとしたデータテーブルコンポーネントとしてmaterial-tableというOSSがあります。

material-tableを使うことにより、Reactの標準のデータテーブルコンポーネントよりもフィルター、検索、ソートなどのテーブル機能を拡張することができます。

今回は、このmaterial-tableをReact + Material-UIで作った画面に導入してみました。

アウトプット

次のようなmaterial-tableのデータテーブルを持ったページを作成します。 image.png

環境

OS、Node,js、npm、TypeScriptのバージョンは次の通りです。

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.6
BuildVersion:   19G73

% node -v
v12.14.0

% npm -v
6.13.4

% npx tsc --version            
Version 3.9.7

作成

進め方としては、まず以下の記事の内容でReact + Material-UIの画面を作成します。(文中での「元記事」はこの記事を指します)

その次に作成した画面に対してmaterial-tableを導入します。

React + Material-UIの画面作成

Reactアプリを新規作成します。

% npx create-react-app react-material-ui-sample --typescript

必要なディレクトリを作成します。

% cd react-material-ui-sample
% mkdir src/components
% mkdir src/components/templates
% mkdir src/components/pages

トップページと商品ページを作成します。(作成内容は元記事を参照)

% touch src/components/pages/HomePage.tsx
% touch src/components/pages/ProductPage.tsx

ページのルーティングに必要なライブラリをインストールします。

% npm install --save react-router-dom
% npm install --save-dev @types/react-router-dom

App.tsxを編集してルーティングを実装します。(編集内容は元記事を参照)

% vi App.tsx

すると編集後のApp.tsxで次のエラーが出ました。

image.png

Could not find a declaration file for module 'react'. '/Users/wakatsuki.ryuta/react-material-ui-sample/node_modules/react/index.js' implicitly has an 'any' type.
  If the 'react' package actually exposes this module, consider sending a pull request to amend 'https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react`ts(7016)

事例を探したところ次の記事が参考になりました。

tsconfig.json"noImplicitAny": false,を追加したらエラーは解消されました。

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react",
    "noImplicitAny": false,
  },
  "include": [
    "src"
  ],
}

Material-UIをインストールします。

% npm install --save @material-ui/core @material-ui/icons

public/index.htmlのヘッダーにGoogle日本語フォントのCDNのURLを追加します。(編集内容は元記事を参照)

% vi public/index.html

ページのテンプレートを作成します。(作成内容は元記事を参照)

% touch src/components/templates/GenericTemplate.tsx

トップページと商品ページを編集してテンプレートを適用します。(編集内容は元記事を参照)

% vi src/components/pages/HomePage.tsx
% vi src/components/pages/ProductPage.tsx

商品ページを編集してTableコンポーネントを導入します。(編集内容は元記事を参照)

% vi src/components/pages/ProductPage.tsx

Reactアプリを起動します。

npm start

http://localhost:3000/productsにアクセスします。

React + Material-UIにより、次のようなMaterial-UI標準のデータテーブルを持ったページを作成することができました。 image.png

material-tableの導入

次にmaterial-tableによる商品ページを作成します。

material-tableのGet Startedを参考に、必要なライブラリをインストールします。なお@material-ui/coreは前項でインストール済みです。

material-tableをインストールします。

% npm install --save material-table@1.66.0

src/components/pages/ProductPage.tsxを次のように変更します。

import React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import MaterialTable from 'material-table';
import GenericTemplate from '../templates/GenericTemplate';

type Props = {} & RouteComponentProps<{}>;

const ProductPage: React.FC<Props> = (props) => {
  return (
    <GenericTemplate title={'商品ページ'}>
      <MaterialTable
        columns={[
          { title: '商品名', field: 'itemName' },
          { title: 'カテゴリー', field: 'category' },
          { title: '重量(g)', field: 'weight' },
          { title: '価格(円)', field: 'price' },
        ]}
        data={[
          { itemName: 'チョコレート', category: 'お菓子', weight: 100, price: 120 },
          { itemName: 'ケーキ', category: 'お菓子', weight: 400, price: 480 },
          { itemName: 'りんご', category: 'フルーツ', weight: 500, price: 360 },
          { itemName: 'バナナ', category: 'フルーツ', weight: 200, price: 300 },
          { itemName: 'みかん', category: 'フルーツ', weight: 250, price: 180 },
        ]}
        options={{
          showTitle: false,
        }}
      />
    </GenericTemplate>
  );
};

export default withRouter(ProductPage);

material-tableの定義は<MaterialTable/>タグの中で行います。タグの中で設定可能なプロパティは下記ページに一覧があります。

http://localhost:3000/productsにアクセスします。

次のようなmaterial-tableのデータテーブルを持ったページを作成することができました。 image.png

おわりに

React + Material-UIの画面にmaterial-tableを導入してみました。

material-tableは、Material-UI標準のデータテーブルと比べて微調整をしなくても既定でデザインが良い感じですし、便利な機能の追加も容易なので便利ですね。

個人的には今までどこまでがMateril-UIでどこまでがmaterial-tableの機能なのかイマイチ理解できてなかったので整理できて良かったです。

参考

以上