reduxを試してみた(1日目) - Reduxをざっくり理解する


React.jsと組み合わせるfluxのライブラリreduxを試してみた。 **このページは作業ログです。やったことをつらつら書くだけなのでまとめません。あしからず。**

## 対象読者

- 主に自分


## ゴール

- 最近のJavaScript開発環境に馴染むこと
- reduxを使ったアプリケーション開発がどんなものか理解できていること

### reduxを試した理由

- React.jsと組み合わせるfluxの中で最右翼
- 今作っているSPAアプリがある程度複雑になりそうなのが見えているため
- ([Mithrill](http://mithril.js.org)くらいシンプルな方が良さそうな気がする)

## やったことメモ

### node.jsの更新

まずはnodeを更新しようと思い、下記のコマンドを実行。

```sh
$ brew update
```

すると`Error: uninitialized constant Formulary::HOMEBREW_CORE_FORMULA_REGEX. Please report this bug: ...`と表示された。[Homebrewのページ](https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Troubleshooting.md#troubleshooting)によると、もう一度`brew update`すればいいらしい。

```sh
$ brew update
$ brew upgrade node
$ node -v
v0.12.7
```

### 開発に必要なツール群のインストール

- [babel](https://babeljs.io/) - ES6のトランスパイラ。reduxのexampleですらES6で追加された`import`文が登場するので必須。`babel-node`というES6で書かれたスクリプトを`node.js`で動かすラッパーもある。
- [webpack](http://webpack.github.io/) - JavaScriptに限らずHTMLやCSSも含んだあらゆる依存を静的なassetに合成するツール。[リンク先の解説ページによると画像なんかも埋め込める。](http://liginc.co.jp/web/js/other-js/148813)

### babelのインストール

```sh
$ npm install -g babel
```

これで`babel-node`もインストールされた。

### webpackのインストール

```sh
$ npm install -g webpack
```

### reduxのexampleを動かす

#### リポジトリのclone

```sh
$ git clone git@github.com:rackt/redux.git
$ cd redux
```

#### リリース版をcheckout

masterは開発版であることが多く、安定していないかもしれないので、タグを見てリリース版をcheckoutする。githubのリポジトリを見てもよさげ。

```sh
$ git tag
$ git checkout v1.0.1
```

#### exampleのビルド

JavaScriptだからbuild不要だと思ってたら、ES6で書かれているから変換が必須。`bundle.js`

```sh
$ npm run build
# なにかエラーがあったら「コマンドが足りていない」等なので適宜対応する。
```

#### exampleを動かす

```sh
$ cd examples
$ ls
async       buildAll.js counter     real-world  testAll.js  todomvc
```

v1.0.1時点では下記の4つがexampleにて公開されている

- async : redditから指定したタグのコンテンツを取得し、一覧作成
- counter : ボタンを押した回数を数えるカウンタ
- real-world : GitHubの情報を取得して表示
- todomvc : [TodoMVCのredux版の実装](http://todomvc.com/)

`async`、`real-world`はredditやGitHubに接続するので、ネット環境がない場合は動作しない。

## ドキュメントを読んでみる

[Reduxに関するドキュメントは、racktというReact.jsのコミュニティにドキュメントが公開されている。](http://rackt.github.io/redux/index.html)

平易な英語で書かれているので読みやすい。

Reduxを一言で言うと、予測可能な状態を作るための入れ物(Redux is a predictable state container)だそう。読み進めていくにつれ、確かにそうだと思った。

ところで[タイムトラベル(TimeTravel)ってなんぞ？](https://github.com/rackt/redux/issues/113) Undo/Redoとか特定の時点での状態を取り出せるってこと？

### 1.1 動機

[ドキュメント](http://rackt.github.io/redux/docs/introduction/Motivation.html)

MutationとAsynchronousの2つからくる複雑さを解決するためのライブラリがRedux。アプリケーションが持つ状態はMutableだし、それが非同期(Asynchronous)に変わるからアプリケーションが複雑になりがちだから、作ったらしい。

### 1.2 3つの原則

[ドキュメント](http://rackt.github.io/redux/docs/introduction/ThreePrinciples.html)

- 真実は1つ(Single source of truth) : 唯一のstoreオブジェクトにアプリケーション全体の状態を持たせる
- 状態は読み取り専用(State is read-only) : 状態変更には明確に何が起きるのかわかるactionを使う
- 状態変更は関数で書く(Mutation are written as pure functions) : 状態のオブジェクトツリーがどう変わるのかを明確に表現するためにreducerを実装する

### 1.3 既知の技術(Prior Art)

[ドキュメント](http://rackt.github.io/redux/docs/introduction/PriorArt.html)

Reduxを実装する際、参考にした既存技術がまとまっているみたい。

- Flux : ReduxはFluxの実装ではあるが、Fluxではない。Dispatcherにはコンセプトがないのと、Stateオブジェクトを必ずImmutableになるよう扱うところがFluxとは違うらしい。Fluxよりもシンプルで十分なアーキテクチャに見える。(私見)
- Elm : ある状態+アクション=次の状態`(state, action) => state`というアーキテクチャを推奨した関数型プログラミング言語
- Immutable : JavaScriptのオブジェクトのデータ構造を永続化するライブラリ。
- Baobab : 大体同上
- Rx : リアクティブプログラミング！

### 2. Reduxの基本

[ドキュメント](http://rackt.github.io/redux/docs/basics/index.html)

Redux自体はFluxパターンの実装という位置づけのためReactに依存していない。ビューにEmberでもAngularでもjQueryでもいける、と書かれている。そのため、このドキュメントはReact以外の部分から解説が始まる。

- Actions : Storeに送るデータ。Fluxとは異なり、副作用を作らないためにJavaScript Objectを返すだけの実装。
- Reducers : Actionによって起きたイベントからアプリケーションの状態を変更する。アプリケーション全体のスコープで管理するstateオブジェクトを適宜分割して状態を管理するのがRedux way。
- Store : Storeはアプリケーションの状態の管理とActionが起きた時のイベントを受け取る。イベントを受け取った時に通知するListenerも登録できる。
- Dataflow : 
- Using with React : ここでReactとの組み合わせを解説


#### 2.1 Actions

[ドキュメント](http://rackt.github.io/redux/docs/basics/Actions.html)

アプリケーションからイベントを受け取り、Storeにデータを送る。イベントの種別毎に`type`を定義する。

#### 2.2 Reducers

[ドキュメント](http://rackt.github.io/redux/docs/basics/Reducers.html)

実装順は下記のように考える。

1. アプリケーション全体の状態オブジェクトを設計する
2. アクション毎の状態の操作をプロパティ毎に実装する
3. `combinedReducer()`でそれぞれのプロパティ毎の操作を行うfunctionをガチャコンする

#### 2.3 Store

[ドキュメント](http://rackt.github.io/redux/docs/basics/Store.html)

Storeクラスが担う責務は下記の4つ

- アプリケーションの状態の保持
- 状態へのアクセッサ : getState()
- 状態を更新する : dispatch(action)
- リスナの登録 : subscribe(listener).


Storeの作成`createState()`の最初の引数はReducerで必須。初期状態があるのであれば、2つ目の引数で受け取る。

StoreオブジェクトがReduxの中心的なオブジェクト。

#### 2.4 Data Frow

[ドキュメント](http://rackt.github.io/redux/docs/basics/DataFlow.html)

Reduxのアーキテクチャは双方向にデータをやりとりしないことを厳格に採用している。それにより、データのライフサイクルが全て同じようになる。Reduxのライフサイクルは下記の4つ

1. store.dispatch(action)を呼ぶ
2. reducerを実行し、stateを更新する
3. 複数のreducerをまとめたroot reducerを実行し、stateのオブジェクトツリーを更新する
4. storeは更新されたstateのオブジェクトツリーを保持し、Listenerに通知

#### 2.5 Reactとつなげる

[ドキュメント](http://rackt.github.io/redux/docs/basics/UsageWithReact.html)

ReactのComponentとバインディングするモジュールをインストール

```sh
$ npm install --save react-redux
```

SmartとDumbの2種類のコンポーネントがあるが、実装ではあまり意識しない。コンテナはSmartコンポーネント、個々の要素はDumbコンポーネントと考えれば大体OKっぽい。

## 1日目で学んだこと

- redux は思ったよりも簡単そう
- Actionを定義し、Action毎にreducerを定義し、storeを変更していく流れはわかりやすい
- webpackやReactの方を知らなさすぎる。特にReactでComponentのイベントハンドラからActionを作る流れがわからない
- reduxのstateの変更をComponentに渡していくあたりがよくわからない
- reduxのボイラープレートを使って簡単なアプリを組みたい

### 関連エントリ

- [2日目はこちら - React.jsを学ぶ](http://qiita.com/kompiro/items/7fe90c4abc92fd32b343)
- [3日目はこちら - redux-boilerplateを使ってひな形を生成する](http://qiita.com/kompiro/items/867c55b32df57cff15bb)
- [(番外編)Webpackはじめの一歩](http://qiita.com/kompiro/items/8337f28271b66957780e)
- [4日目はこちら - redux-react-routerを試す](http://qiita.com/kompiro/items/de10197368f864c2e846)
- [5日目はこちら - ajaxを使ってUIを構築する](http://qiita.com/kompiro/items/d1ffcfcba7cc34d364f0)