前回(Vol1)はこちら
http://qiita.com/nakadoribooks/items/a31a85c788bbc90baf56
Ios実装は(ReSwift)こちら
http://qiita.com/nakadoribooks/items/430aba2efacbf42f0430
成果物
https://github.com/nakadoribooks/CalilClient-web/releases/tag/vol2
ActionCreator リファクタリング
- ActionCreator 内でのDispatchしない
ライブラリ取り込み
ES2015 は デフォルトでPromise 使えるので特になし。
ActionCreator
ActionCreator.js
static loadLibraries(prefName="秋田県") {
var params = { appkey: config.API_KEY, pref: prefName, format: "json", callback: "f" };
return new Promise((resolve, reject) => {
superagent.get(config.API_LIBRARY).query(params).use(superagentJsonp({timeout: 1000}))
.end(function(err, res){
// error
if(err != null){
let errorAction = Object.assign(LibraryListFailLoadAction)
resolve(errorAction)
return;
}
// success
var libraryList = Library.createList(list)
var loadedAction = Object.assign(LibraryListLoadedAction)
loadedAction.libraryList = libraryList
resolve(loadedAction)
})
})
}
static loadLibrariesAction(){
return Object.assign(LibraryListLoadAction)
}
変更前
// ActionCreator interface
static loadLibraries(prefName="秋田県") // return Action
// 使う側 (View)
let action = ActionCreator.loadLibraries();
store.dispatch(action);
変更後
// ActionCreator interface
static loadLibraries(prefName="秋田県") // return Promise<Action>
static loadLibrariesAction() // return Action
// 使う側 (View)
let action = ActionCreator.loadLibraries().then((action)=>{
store.dispatch(action)
})
store.dispatch(ActionCreator.loadLibrariesAction())
たぶんこっちの方が好ましい。
※ 追記 redux-thunk 使用バージョン
コメントいただいたので redux-thunk のやつ。
redux-thunk
https://github.com/gaearon/redux-thunk
Midlewareと呼ばれるものの一種。
なにやらstore.dispatch()に関数が渡せるようになるよう。
dispatch(function(f){
// ごにょごにょして
// 引数にもらった コールバックにActionを渡してやる
f(action)
})
成果物
https://github.com/nakadoribooks/CalilClient-web/releases/tag/vol2.5
準備
package.json
redux-thunk 取り込み
package.json
{
// 〜 略 〜
"dependencies": {
"redux": "3.0.0",
"redux-thunk": "2.2.0" , // ← これ追加
"superagent": "3.5.0",
"superagent-jsonp": "0.1.1"
}
}
Middleware 登録
main.js
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk'; // ← これと
import reducer from './model/reducer/CalilReducer.js'
import LibraryListViewController from './vc/list/LibraryListViewController.js'
// setup redux. put global
const store = createStore(
reducer
, applyMiddleware(thunk) // ← これ
)
window.store = store;
ActionCreator
ActionCreator.js
class ActionCreator{
static loadLibraries(prefName="秋田県"){
return function (dispatch) {
ActionCreator._loadLibraries(prefName).then(
libraryList => {
var loadedAction = Object.assign(LibraryListLoadedAction)
loadedAction.libraryList = libraryList
dispatch(loadedAction)
},
error => {
let errorAction = Object.assign(LibraryListFailLoadAction)
dispatch(errorAction)
}
);
};
}
static _loadLibraries(prefName) {
var params = { appkey: config.API_KEY, pref: prefName, format: "json", callback: "f" };
return new Promise((resolve, reject) => {
superagent.get(config.API_LIBRARY).query(params).use(superagentJsonp({timeout: 1000}))
.end(function(err, res){
// error
if(err != null){
reject()
return;
}
var list = res.body
// wrong dictionary
if (list == null){
reject()
return;
}
// success
var libraryList = Library.createList(list)
// 時間かかっているてい
setTimeout(function(){
resolve(libraryList)
}, 1000)
})
})
}
static loadLibrariesAction(){
return Object.assign(LibraryListLoadAction)
}
}
export default ActionCreator
変更前
// ActionCreator interface
static loadLibraries(prefName="秋田県") // return Promise<Action>
static loadLibrariesAction() // return Action
// 使う側 (View)
let action = ActionCreator.loadLibraries().then((action)=>{
store.dispatch(action)
})
store.dispatch(ActionCreator.loadLibrariesAction())
変更後
// ActionCreator interface
static loadLibraries(prefName="秋田県") // return function (dispatch) {}
static loadLibrariesAction() // return Action
// 使う側 (View)
store.dispatch(ActionCreator.loadLibraries())
store.dispatch(ActionCreator.loadLibrariesAction())
なるほど。