React + OnsenUI for Reactの基本コンポーネント② (Navigator・Toolbar編)

# 概要

* [前回](http://qiita.com/gcfuji/items/31c8da84a1cd17a5cb9f)に引き続き、OnsenUI for Reactの基本コンポーネントについて解説していきます。

* 今回は\<Page>よりもルートに存在し、\<Page>の遷移状態を管理する\<Navigator>と、よくあるツールバーのUIを簡単に実装できる\<Toolbar>について調査しました。

# 成果物

前回の\<Button>, \<Page>と今回の\<Navigator>, \<Toolbar>の4つのコンポーネントのみで簡単な遷移アプリを作成しました。

![push.gif](https://qiita-image-store.s3.amazonaws.com/0/129216/4bd03edf-b7c5-6636-fc28-66eecc555a54.gif)

# Component

## Navigator Component

各ページの遷移状態を管理するコンポーネントです。
\<Page>は各ページそのものを表すコンポーネントだが、それらのページの遷移状態や遷移時のアクション・アニメーションなどを管理するルートコンポーネントにあたるのがNavigatorコンポーネントです。

今回作成したNavigatorが以下のソースです。

```js:src/Foo/FooNavigator.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Navigator } from 'react-onsenui';

// 後で実装するInitialPage
import FooMain from './FooMain.jsx';

// FooNavigatorクラスを定義
export default class FooNavigator extends React.Component {
  constructor(props) {
    super(props);

    // thisをクラスに固定
    this.renderPage = this.renderPage.bind(this);
  }

  // renderPageのPropsに与える関数
  // ・現在のrouteの情報(route)とnavigatorオブジェクトを引数にとる
  // ・navigator.pushPage(route)される度にrenderPageが実行される。
  renderPage(route, navigator) {
    // 現在のページのpropsがあればpropsを代入する。
    const props = route.props || {};
    // 現在のnavigatorオブジェクトをprops.navigatorに代入する。
    props.navigator = navigator;
    // keyが無いとReactに怒られる為、routeオブジェクトに代入したtitleを一意の値として渡す。
    props.key = route.title;
    // createElementで仮想DOMを作成する。
    return React.createElement(route.component, props);
  }

  render() {
    return (
      <Navigator
        renderPage={this.renderPage}
        // 初期ページのInitial値を代入
        initialRoute={
          {
            component: FooMain,
            title: 'FirstPage'
          }
        }
      />
    );
  }
}

```

Reactベースとなっている為、OnsenUI 1.x とは実装が少し変わっていて、戸惑いました。
普段のReactの実装であまり使わない(jsxではあまり使わない),createElementも最初に出てきた時抵抗感がありました。
慣れたらなんて事なさそう。

propsで各\<Page>に渡す[navigator]オブジェクトは、pushPage(route)やpopPage(route)のメソッドを持ち、Navigator以下の\<Page>で利用できます。

次は、NavigatorのInitialページにあたるFooMainを実装します。

```js:src/Foo/FooMain.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Page, Button, Toolbar } from 'react-onsenui';

import ons from 'onsenui';
import FooDetail from './FooDetail.jsx';

export default class FooMain extends React.Component {
  constructor(props) {
    super(props);
    this.pushDetailPage = this.pushDetailPage.bind(this);
  }

  // pushPage()のハンドラー関数
  pushDetailPage() {

    // propsに格納されているnavigatorオブジェクトのpushPageで遷移したいページの情報を渡す。
    this.props.navigator.pushPage({
      component: FooDetail,
      title: 'FooDetail'
    });
  }

  render() {
    return (
      <Page>
        <Toolbar>
          <div
            className="center"
          >
            BookMain
          </div>
        </Toolbar>
        <Button
          onClick={this.pushDetailPage}
          className="gcButton"
        >
          PushPage
        </Button>
      </Page>
    );
  }
}

FooMain.defaultProps = {
  title: 'FirstPages'
};

FooMain.propTypes = {
  title: React.PropTypes.string,
  navigator: React.PropTypes.any.isRequired
};
```

こちらは普通のReactみたいな感じで書けます。
props.navigator.pushPage(route)で遷移したいページに遷移できます。

最後に遷移後のページです。

```js:src/Foo/FooDetail.jsx
import React from 'react';
import ReactDOM from 'react-dom';
// BackButtonコンポーネントはToolbarコンポーネントの仲間です。後述します。
import { Page, Button, Toolbar, BackButton } from 'react-onsenui';

export default class FooDetail extends React.Component {
  render() {
    return (
      <Page>
        <Toolbar>
          <div
            className="center"
          >
            FooDetail
          </div>
          <div
            className="left"
          >
            <BackButton>
              Back
            </BackButton>
          </div>
        </Toolbar>
        <div className="textCenter mTop20">DetailPage</div>
      </Page>
    );
  }
}

```

### Props

|Props|Description|
|-----|-----------|
|renderPage={fn}|ページ遷移時に<Page>をレンダリングする。|
|initialRoute|最初にレンダリングされるページに初期情報を与える。|
|animationOptions|ページ遷移時のアニメーションを指定する。|


## Toolbar Component

次はToolbarコンポーネントです。

Toolbarコンポーネントには仲間がいて、どれも同じ様な感じで実装できます。

### Components

|Component|Description|
|-----|-----------|
|\<BackButton>|ページをキューするボタンを作成します。(戻るボタン)|
|\<BottomToolbar>|下部にツールバーを作成します。|
|\<Toolbar>|上部にツールバーを作成します。|
|\<ToolbarButton>|ツールバー上にボタンを作成します。|

今回は、一番よく使うであろう<Toolbar>に絞って解説します。
<Toolbar>は子要素に<div>を取り、ツールバーの文字の表示位置をclassで指定します。
<div>のテキストに記載した内容がツールバーの文言になります。


### Props

|Props|Description|
|-----|-----------|
|modifier|Props値を変更して見た目を変更する。|

### Modifier

|Modifier|Description|
|--------|-----------|
|material|マテリアルデザインのツールバー|
|transparent|透明なツールバー|


# 終わり

Navigatorは慣れるまでは少しややこしいかもしれませんが、習得必須なコンポーネントですので、早めに慣れましょう。
次回以降のComponentでは、どんどんアプリっぽいものを作成していきたいと思います。
やっぱりReactはかわいいですね。

最終的にはAWSと連携させてAuth付きのユーザー管理システム的なものを作ろう。

続きは次回。


# リンク

* [【本家】Onsen UI for React](https://onsen.io/v2/docs/guide/react/index.html)
* [【本家】Navigator](https://onsen.io/v2/docs/react/navigator.html)
* [【本家】Toolbar](https://onsen.io/v2/docs/react/Toolbar.html)
* [【本家】BottomToolbar](https://onsen.io/v2/docs/react/BottomToolbar.html)
* [【本家】ToolbarButton](https://onsen.io/v2/docs/react/ToolbarButton.html)
* [【本家】BackButton](https://onsen.io/v2/docs/react/BackButton.html)