現在業務で実装しているReact
を用いたデモ的なものにRedux
を導入してみたので、自分なりに理解したものをメモしておく。
Reduxとは
Fluxフレームワークの1つで、現時点(2015/9末)でもっともstar数の多いもの。ちなみにAngular
用にng-redux
というのがあったりもする
参考サイト
インストール
npm install --save react-redux
登場人物
Store
-
state
をもっている -
Action
をdispatchする - Reduxを用いたアプリケーションでは
Store
は1つしか存在しちゃいけない
Reducer
-
state
がどのように変更されるのかをAction
を通して特定するもの - 分割可能(
reducer composition
)
Action
-
Store
に送られる情報 -
Object
型であり、Action
を特定するString
型のtype
プロパティを必ずもつ
Provider
- ルートのコンポーネントを囲うもの。こうすることで、コンポーネント内で
Store
を利用できるようにする - 内部的には
React
のcontext
という機能を利用しているとのこと
メモ
-
Provider
については、データフローの一連の流れとは関係ないものという認識。なので、Store
等と並列に書くのは紛らわしいかもしれない。 -
Reducer
というのがFlux
そのものの中では出てこない考えなので少し戸惑ったけれど、Store
の役割の一部を切り出したものという認識
実装
まだES6を全然キャッチアップできておらず、ちょいちょい古い書き方が混ざっています(とくにモジュール化)。とはいえ逆に同じ状況の人いるかもしれないので、あえてそのままで書いてみます(汗)
Action
actions.js
var Actions = {}
Actions.UPDATE_LIST = 'UPDATE_LIST';
Actions.DONE_ITEM = 'DONE_ITEM';
Actions.updateList = function(list) {
return { type: Actions.UPDATE_LIST, list };
}
Actions.doneItem = function(itemId) {
return { type: Actions.DONE_ITEM, itemId };
}
Reducer
reducer.js
var Reducer = function(state = [], action) {
switch (action.type) {
case Actions.UPDATE_LIST:
return { list: action.list };
case Actions.DONE_ITEM:
return { itemId: action.itemId };
default:
return state;
}
}
Action
とReducer
はコンポーネントとの依存はないので、そこは一切気にせずひたすら書いていく
Store, Provier
※ Main
がルートコンポーネント
Main.js
window.store = createStore(Reducer);
React.render(
<Provider store={store}>
{() => <Main />}
</Provider>,
document.getElementById('content')
);
function mapStateToProps(state) {
return {
itemList: state.list
};
}
Main = connect(mapStateToProps)(Main)
dispatch
※ ItemCell
は子コンポーネントの1つ
ItemCell.js
onClick: function() {
var list = []; // たとえばAjax通信で取得したリストデータ
store.dispatch(Actions.updateList(list));
},
補足
ひっそりとconnect
という処理が入っているけれど、書き方含め(ドットチェーンで繋ぐとかならわかりやすいけど括弧が連続で繋がっていく)これが一番自分としてはわかりづらかった。
Reduxとコンポーネントを文字通り「連結する(connect)」処理には違いないけど、内部的な処理とかはまた追い追い調べたいと思う
よくわかっていないところ
-
connect
でリスナの登録など行っているわけだけど、store.subscribe(listener)
という書き方は基本しないという考えでいいのかな?? -
store.dispatch()
で今回dispatchしているけれど、bindActionCreators
を使うほうがいい??
所感
- 上の「よくわかっていないところ」に書いたように、いろいろな書き方ができるような印象があって、どう書くのがいいのか迷うことがある
- 「子コンポーネントについては一切手をいれなくていい」といったふれこみをどこかで聞いた気がするのですが、そこは確かにそうだと思った
次の課題
- 大規模開発に備えて
Action
とかReducer
の分割を行う -
Middleware
とかさわってみる - ルーティングの処理を入れる(少し試してみたがうまくいかなかった!!)
- 今回書いたもので間違っていること・情報不足していることあれば補足する