Posted at

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

More than 3 years have passed since last update.

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 child into a function. This restriction will be removed with React 0.14.



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

0.14になっての大きな変更の1つに、ReactReactDOMに分かれたことがあると思いますが、そこらへんで修正が必要でした。

とはいえ今回の内容とは関係ないところなので、以下に簡単に書いておくにとどめます。


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をみるほうが良さそう。

他にはReduxのsamplesの中のreal-worldでも使われているので参考にした


実装


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')
);



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)



SomeComponent.js

 <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のサンプルのものを例に出すと


redux-router/examples/basic/server.js

app.get('*', (req, res) => {

res.sendFile(path.join(__dirname, 'index.html'));
});


補足

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