Redux
を用いたときのルーティングを試してみようと思います。
Redux
をつくっているrackt
というコミュニティがルーティングのライブラリを提供しています
バージョン情報
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 child into a function. This restriction will be removed with React 0.14.
React 0.14
でまずエラーが出ると思われること
0.14
になっての大きな変更の1つに、React
とReactDOM
に分かれたことがあると思いますが、そこらへんで修正が必要でした。
とはいえ今回の内容とは関係ないところなので、以下に簡単に書いておくにとどめます。
0.14になってどう変わるかがまとまっているスライド
今回修正した内容
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をみるほうが良さそう。
他にはRedux
のsamplesの中のreal-worldでも使われているので参考にした
実装
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')
);
//...
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)
<Link to={"/"}>TOPへ</Link>
history
history
がないと以下のようなエラーが起きる
Uncaught TypeError: createHistory is not a function
のでインストールする
npm install --save history
子コンポーネントに値を渡す方法
これはredux-router
というよりかはreact-router
に関する話ですが、
<div id="main">
<Header />
{this.props.children && React.cloneElement(this.props.children, {
list : this.props.list
})}
</div>
こんな感じで、子コンポーネントにprops
経由で値を渡すことができる
Link
<Link to={"/"}>TOPへ</Link>
こんな感じでリンクは書く
サーバ側の設定
自分はサーバサイド弱いので一瞬ハマってしまったのですが、サーバ側のルーティングの設定もしてあげないと、当然no route matches
的なエラーが出てしまいます。redux-router
のサンプルのものを例に出すと
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
補足
今後も各種API変わると思うので、3ヶ月後には使い物にならない記事だと思います