redux Vol2

前回(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

```swift: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 取り込み

```json:package.json
{
  // 〜 略 〜
  "dependencies": {
    "redux": "3.0.0",
    "redux-thunk": "2.2.0" , // ← これ追加
    "superagent": "3.5.0",
    "superagent-jsonp": "0.1.1"
  }
}
```

Middleware 登録

```javascript: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

```swift: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())

```

なるほど。