ReactJS入門@ES6:ReactRouter編

**対象者：私を含むReact初心者**
前：[ReactJS入門@ES6:コンポーネント編](http://qiita.com/HIGAX/items/54aee0f94643bcbddb81)
次：[ReactJS入門@ES6:Redux編](http://qiita.com/HIGAX/items/dbaf31d4c41c510f84f9)

***

### 前提

ReactRouterのbrowserHistoryを使用する。

追記：下記mod_rewriteの設定は私の環境では必要ありませんでした。
逆に必須だったのは、```<base>```の設定でした。

index.htmlにリクエストを投げるためApacheのmod_rewriteモジュールを使用。

```
<ifModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule (.*) index.html [L,QSA]
</ifModule>
```

私の環境ではHTMLにベースの指定が必要だった。

```html
<body>
  <base href="/" />
</body>
```

***

### サンプル概要

作成するサンプルの概要。
トップ画面 ▶ ユーザ画面 ▶ アイテム画面 というシンプルな構成。

|画面|説明|URL|
|---|---|---|
|トップ|ヘッダを表示|http://ex/|
|ユーザ|指定したユーザ情報を表示|http://ex/user/{userName}|
|アイテム|指定したユーザのアイテムを表示|http://ex/user/{userName}/item/{itemId}|

追記：書き忘れていましたが、
今回はURLパラメータを処理するサンプルとなっているので、
{userName}や{itemID}の部分をブラウザのURL入力欄で適当に書き換えても動作します。

***

### ルーティングの設定

実際のコードとは異なるが、今回は雰囲気を掴みやすくするために、
ルーティングの設定から記述する。

今回はReactDOM.renderに直接指定している。

```js
ReactDOM.render((
  <Router history={browserHistory}>
    <Route path="/" component={App}>
      <Route path="user/:userName" component={User}>
        <Route path="item/:itemId" component={Item} />
      </Route>
    </Route>
  </Router>
), document.getElementById('wrapper'));
```

***

### コンポーネント作成

今回は1コンポーネント1画面という前提で作成。
画面移動用のボタンはReactRouterのLinkクラスで描画する。

```js
<Link to={'/sample'} activeClassName="active">Sample</Link>
```

URLパラメータは```this.props.params```から取得する。

#### Appコンポーネントを作成

ルートコンポーネント

```js
class App extends React.Component {
  render() {
    return (
      <div>
        <ul>
          <li><Link to="/" activeClassName="active">Index</Link></li>
          <li><Link to="/user/kinjo" activeClassName="active">User:KINJO</Link></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
}
```

#### Userコンポーネントを作成

URLパラメータで指定したuserNameを表示するコンポーネント
文字列中の変数を展開するために、ES6のテンプレートリテラルを使用しています。

```js
class User extends React.Component {
  render() {
    const { userName } = this.props.params;

    return (
      <div className="User">
        <h1>User Name: {userName}</h1>
        <ul>
          <li><Link to={`/user/${userName}/item/1`} activeClassName="active">Item:1</Link></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
}
```

#### Itemコンポーネントを作成

URLパラメータで指定したItemIdを表示するコンポーネント

```js
class Item extends React.Component {
  render() {
    const { userName, itemId } = this.props.params;
    return (
      <div className="Item">
        <h2>User Name: {userName}</h2>
        <h2>Item ID: {itemId}</h2>
      </div>
    )
  }
}
```

***

### 親コンポーネントの役目は子コンポーネントを表示すること

ユーザ画面（User）を表示しているのは、
親コンポーネント（App）の```{this.props.children}```であり、
アイテム画面（Item）を表示しているのは、
親コンポーネント（User）の```{this.props.children}```である。

***

### 動的な画面遷移を行う

contextTypesでrouterを設定することにより、
```this.context.router.push();```が使えるようになる。

EX :

```js
class Item extends React.Component {
  static contextTypes = {
    router: React.PropTypes.object.isRequired
  };
  componentWillMount() {
    //this.context.router.push('/user/unknown');
  }
  render() {
    const { userName, itemId } = this.props.params;
    return (
      <div className="Item">
        <h2>User Name: {userName}</h2>
        <h2>Item Id: {itemId}</h2>
      </div>
    )
  }
}
```