最終更新日:170711 原本2017/04/12 

CodeZine(コードジン)

React×Material-UIでモダンなUIを実装する

基礎からはじめるReact入門 第3回

 Reactはコンポーネントを組み合わせて開発を行うことで、保守性の高いアプリケーションを実現できるライブラリです。同時に、優れたUIを提供するライブラリでもあります。前回はReactコンポーネントの基本であるPropsとState、およびライフサイクルについて解説しました。本稿ではデザイン性をアップさせてくれるサードパーティー製のコンポーネントセット、Material-UIの使用方法について紹介します。Material-UIは、Googleのデザインガイドラインに則って開発されたコンポーネントのライブラリで、活用することで簡単に見栄えのいいアプリを作ることができます。

対象読者

  • JavaScriptとWeb開発の基礎に理解がある方
  • Reactに興味/関心があり、これから学び始める方

前提環境

  • macOS Sierra 10.12
  • Node.js v6.6.0/npm 3.10.3
  • React 15.4.0
  • Material-UI 0.16.7

Material-UIの導入編

 最近のエンドユーザーは優れたデザインを兼ね備えた多くのプロダクトに慣れ親しんでおり、それなりに利用されるものを作るには、アプリの機能だけでなくデザインも重要な要素です。

 Yahoo! Japanは検索窓の枠を1ピクセル太くしただけで約5億円の広告収入増を達成した、というニュースが以前話題になりましたが、デザインが再訪問率やコンバージョン率に与える影響はますます大きくなっています。こういった背景から、新しいプロダクトを作る場合にはデザイナーを含めたチームを構成してプロジェクトを進めるべきですが、なんらかの制約でデザイナーを確保できず、デザインを勉強したことのないエンジニアが、UIの優れた成果物をアウトプットしなければいけない状況もあるでしょう。

 Reactではサードパーティーによって開発された、さまざまなコンポーネントがMITライセンスで公開されています。これらを活用することで、ある程度しっかりした作りのアプリを比較的容易に開発できるようになります。利用目的がはっきりと決まっている場合はGitHubに公開されているコンポーネントを利用してもいいですが、ここでは最も有名なコンポーネントセットの一つである、Material-UIを利用する方法を紹介したいと思います。

図1 Material-UI公式トップ
図1 Material-UI公式トップ

 冒頭でご紹介した通り、Material-UIはGoogleのデザインガイドラインに沿って開発されたコンポーネントセットであり、npmパッケージとして提供されています。画面内の部品に相当するReactコンポーネント群と、画面全体の色調を設定するテーマの二つを組み合わせてアプリを作成します。Material-UIで利用できる全てのReactコンポーネントを本稿で紹介することはできませんが、図2で紹介している通り、ボタンやカレンダー、ダイアログをはじめ、多くのコンポーネントが利用可能となっています。また、個々のコンポーネントとテーマに標準で適用されているデザイン(スタイル)は、必要に応じてカスタマイズすることもできます。

図2 Material-UIで利用可能なコンポーネント
図2 Material-UIで利用可能なコンポーネント

Material-UIのインストール

 Reactプロジェクトのトップディレクトリで下記コマンドを実行し、パッケージをインストールします。Material-UIのコンポーネントでは、タップ系のイベントの取得にreact-tap-event-pluginを利用しています。この依存関係は将来的にはなくなると公式サイトに記載されていますが、現行バージョン(React 15.4.0)ではMaterial-UI導入時にreact-tap-event-pluginも併せてインストールする必要があります。

リスト1 material-uiとreact-tap-event-pluginのインストール
$ npm install --save-dev material-ui
$ npm install --save-dev react-tap-event-plugin

 インストールが完了すると、下図のようにMaterial-UIのパッケージが追加されます。

図3 Material-UIインストール結果
図3 Material-UIインストール結果

Material-UIを実装する

Material-UIの活用

 では、Material-UIを実装する方法を解説していきます。まずはチップとアバターというコンポーネントについて紹介します。チップは角丸の長方形のオブジェクト内に複数の要素を表現できるコンポーネント、アバターは人やものを丸いアイコンで表現するためのコンポーネントです。

 ここで紹介するサンプルでのチップとアバターの関係は、チップにアバターが内包されているというイメージです。下表(表1、表2)のチップとアバターのプロパティ一覧にも記載していますが、チップではonRequestDeleteにコールバックを設定することで削除アイコンを表示させ、ハンドルすることが可能です。アバターは単独で利用されるというよりもチップやリストアイテムといった他のコンポーネントと組み合わせて利用するケースのほうが多いと思います。

表1 チップの主なプロパティ
# プロパティ 説明
1 backgroundColor string 背景色を設定。
2 labelColor string ラベルの色を設定。
3 labelStyle object ラベルのスタイルを設定。
4 onRequestDelete function 削除ボタンクリック時のコールバックを設定。このプロパティが設定された場合に削除ボタンが表示される。
5 onTouchTap function 要素がタップされた時のコールバックを設定。
6 style object スタイルを指定。親要素のスタイルをオーバーライドする場合に利用。
表2 アバターの主なプロパティ
# プロパティ 説明
1 backgroundColor string 背景色を設定。アイコン画像には適用されない。
2 children node 子要素を設定。
3 icon element アバターにSvgIcon、またはFontIconというアイコンコンポーネントを設定。
4 color string アイコンの色を設定。
5 size number アバターのピクセル数を設定。
6 src string アバターに画像を設定。この値が設定される場合はimg要素として描画され、それ以外の場合はdiv要素として描画される。
7 style object スタイルを指定。親要素のスタイルをオーバーライドする場合に利用。

 リスト2と図4は、チップとアバターを利用したサンプルコードとその実行結果です。削除ボタンのクリック時とそれ以外の領域のクリック時に、それぞれhandleTouchDeleteとhandleTouchTapが実行されます。

リスト2 mui-chip-sample/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import ‘./index.css';

// (1)モジュールのインポート
import MuiThemeProvider from ‘material-ui/styles/MuiThemeProvider';
import Avatar from 'material-ui/Avatar';
import Chip from 'material-ui/Chip';
import injectTapEventPlugin from 'react-tap-event-plugin';

// (2)タッチイベントに必要なコード
//    http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();

const styles = {
  chip: {
    margin: 5,
  },
  wrapper: {
    display: 'flex',
    flexWrap: 'wrap',
  },
};

// (3)タップイベントのハンドラ
function handleTouchDelete() {
  alert('削除ボタンが押されました');
}

function handleTouchTap() {
  alert('チップが選択されました。');
}

// (4)Material-UIのコンポーネントの宣言
class MyChipSmaple extends React.Component {
  render() {
    return (
        <MuiThemeProvider>
      <div style={styles.wrapper}>
        <Chip
          onRequestDelete={handleTouchDelete}
          onTouchTap={handleTouchTap}
          style={styles.chip} >
          <Avatar size={32}>TS</Avatar>
          Taro Sakurai
        </Chip>

    [繰り返しのため省略]

        </MuiThemeProvider>
    );
  }
}

ReactDOM.render(
  <MyChipSmaple />,
  document.getElementById('root')
);
図4 実行結果
図4 実行結果

 実行結果の通り、Material-UIを利用すると今風のUIのウィジェットを簡単に表示することができます。(1)でモジュールを読み込み、(4)で宣言したコンポーネントをReactDOM.renderメソッドで描画することでMaterial-UIを利用しています。また、宣言したコンポーネント内でチップを呼び出し、同時にイベントハンドラの設定、およびコンテンツの表示を行っています。ここで言及すべきポイントは、Material-UIで提供されるコンポーネントを利用するためにテーマを適用する必要があるということです。(4)のように、MuiThemeProviderを最上位の階層としてチップやアバターのコンポーネントを呼び出すことにより、Material-UIのデザインがウィジェットに適用されます。(2)はインストール時にも触れましたが、タップイベント系取得に必要な設定で、アプリの最初に書くおまじないのようなものです。

MuiThemeProviderについて

 Material-UIで提供されるMuiThemeProviderをカスタマイズすることで、アプリ全体のデザインを変更することができます。標準で提供されているスタイルには、lightBaseTheme(デフォルト設定)とdarkBaseThemeがあります。darkBaseThemeを適用する場合は、以下のようなモジュールの読み込みとテーマ適用の設定を行います。

リスト3 darkBaseThemeスタイルとスタイルを適用するgetMuiThemeメソッドの読み込み
import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
リスト4 コンポーネントの宣言、MuiThemeProviderへのテーマ適用
class MyButton extends React.Component {
  render() {
    return(
      <MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
        <RaisedButton label="MyButton" />
      </MuiThemeProvider>
    );
  }
}

 また、さらに細やかなスタイルの変更は、 muiThemeオブジェクトのプロパティの設定を個別にすることで実現できます。muiThemeオブジェクトには、コンポーネント間の間隔やフォント、要素のカラーといったさまざまな設定がされています。コンポーネント宣言時にカスタマイズしたテーマを適用することで、思い通りのデザインのアプリを作ることが可能です。カスタマイズ可能な項目は以下の表の通りです。

表3 muiThemeの主なプロパティ
# プロパティ 説明
1 spacing コンポーネント間の間隔を設定。
2 fontFamily デフォルトのフォントを設定。
3 palette ウィジェットやテキストの色を設定。
4 zIndex コンポーネントの重なりの順序を指定。
5 isRTL 文字が右から左に表示されるように指定。
6 App Bar、Avatar等 個別のコンポーネントのスタイルを指定。

 実装方法は、引数にJSONファイルとしてカスタマイズしたい項目をセットしてgetMuiThemeメソッドを呼び出し、戻り値のmuiThemeオブジェクトをMuiThemeProviderコンポーネント生成時のPropsとして設定します。

リスト5 MuiThemeProviderのカスタマイズ方法
// カスタマイズしたい項目の設定
const muiTheme = getMuiTheme({
  palette: {
    primary1Color: blue500,
  },
  RaisedButton: {
    width: 80,
  },
});

// PropsとしてmuiThemeオブジェクトを設定
const Main = () => (
  <MuiThemeProvider muiTheme={muiTheme}>
    <RaisedButton label="My Button” />
  </MuiThemeProvider>
);

まとめ

 今回は、Reactコンポーネントセットの一つである、Material-UIを紹介しました。他にもさまざまなコンポーネントが利用可能なので、ご自身に合ったものをぜひ探してみてください。