Reduxさわってみたのでメモ 【ルーティング】

`Redux`を用いたときのルーティングを試してみようと思います。
`Redux`をつくっている`rackt`というコミュニティがルーティングのライブラリを提供しています

https://github.com/rackt/redux-router

# バージョン情報

`React`自体のバージョンがまだ`0.1X`とモラトリアム期間中のため、`React`はもちろんその周辺のライブラリも活発に開発が進んでいるいま、バージョンにはかなり気をつける必要があります

- react        : `0.14.0-rc1`
- react-dom    : `0.14.0-rc1`
- react-router : `1.0.0-rc1`
- redux        : `3.0.2`
- react-redux  : `2.1.2`
- redux-router : `1.0.0-beta3`

ポイントは、`redux-router(現時点で最新の1.0.0-beta3)`は`Reactの0.13.X`には対応していないことです。

> With React 0.13, you need to wrap <Provider> child into a function. This restriction will be removed with React 0.14.

# `React 0.14`でまずエラーが出ると思われること

`0.14`になっての大きな変更の１つに、`React`と`ReactDOM`に分かれたことがあると思いますが、そこらへんで修正が必要でした。
とはいえ今回の内容とは関係ないところなので、以下に簡単に書いておくにとどめます。

### 0.14になってどう変わるかがまとまっているスライド

https://speakerdeck.com/koba04/reactjs-v0-dot-14-changes

### 今回修正した内容

```
React.render(
```

を以下に修正

```
ReactDOM.render(
```
あと試しに入れていたUIまわりのライブラリが依存関係でエラー出たので、一旦それも外しました


# 実装する

https://github.com/rackt/redux-router
を参考に以下のように実装。ちなみに現時点(2015/10/8)だと、`README.md`に

> Documentation is in progress. Please refer to the basic example in the meantime.

とあるのでその[example](https://github.com/rackt/redux-router/tree/master/examples/basic)をみるほうが良さそう。

他には`Redux`のsamplesの中の[real-world](https://github.com/rackt/redux/tree/master/examples/real-world)でも使われているので参考にした


### 実装

```js:index.js
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { createStore, compose, combineReducers } from 'redux';

import {
  ReduxRouter,
  routerStateReducer,
  reduxReactRouter
} from 'redux-router';

import { Route, Link, IndexRoute } from 'react-router';
import { Provider, connect } from 'react-redux';
import createHistory from 'history/lib/createBrowserHistory';

// ルーティングの設定
const routes = (
  <Route path='/' component={Main} >
    <IndexRoute component={MainList} />
    <Route path="*" component={NotFound}/>
  </Route>
)

// reducer
const reducer = combineReducers({
  router  : routerStateReducer,
  data    : Reducer
});

// store
const store = compose(
  reduxReactRouter({ routes, createHistory })
)(createStore)(reducer);

// render
ReactDOM.render(
  <Provider store={store}>
    <ReduxRouter/>
  </Provider>,
  document.getElementById('content')
);
```

```js:Main.js

//...

render() {

    return (
      <div>
        <SideMenu />
        <div id="main">
          <Header />
          {this.props.children && React.cloneElement(this.props.children, {
            list : this.props.list
          })}
        </div>
      </div>
    );
  }

// ...

function mapStateToProps(state) {
  return {
    route : state.router
  }
}

export default connect(mapStateToProps)(Main)
```


```js:SomeComponent.js
 <Link to={"/"}>TOPへ</Link>
```


## history

`history`がないと以下のようなエラーが起きる

> Uncaught TypeError: createHistory is not a function

のでインストールする

```
npm install --save history
```


## 子コンポーネントに値を渡す方法

これは`redux-router`というよりかは`react-router`に関する話ですが、

```js
        <div id="main">
          <Header />
          {this.props.children && React.cloneElement(this.props.children, {
            list : this.props.list
          })}
        </div>
```

こんな感じで、子コンポーネントに`props`経由で値を渡すことができる

## Link

```js
 <Link to={"/"}>TOPへ</Link>
```

こんな感じでリンクは書く

## サーバ側の設定

自分はサーバサイド弱いので一瞬ハマってしまったのですが、サーバ側のルーティングの設定もしてあげないと、当然`no route matches`的なエラーが出てしまいます。`redux-router`のサンプルのものを例に出すと

```js:redux-router/examples/basic/server.js
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html'));
});
```

# 補足

今後も各種API変わると思うので、３ヶ月後には使い物にならない記事だと思います