最小のReact+Redux

多分これが一番小さいと思います。

# 前置き
この記事はReactチュートリアルを終え、そのままReduxに入門した初心者が書いています。
もし間違っていることがあれば教えていただけると幸いです。

普通にチュートリアル見て分かる人は見る必要ないと思います。

# 試した環境
* OS：CentOS release 6.7 (Final)
* Node.jsバージョン：v6.1.0

# Reduxわからん
Reactチュートリアルを終え、jQueryやVanillaから仮想DOMに置き換えるとなんかすごいわかりやすい！感動！となっていたところ、なにやらReduxなるものがあるということを耳にする。

データの流れを一方向にする？確かにわかりやすそうだ！早速やってみよう！と公式やQiita等で検索して写経してみたものの、Action, Reducer, container等のよくわからない単語ばっかりでさっぱりでした。

ActionがReducerでReducerはAction + State => NewStateで……

わからなさすぎたので、いろいろな場所から情報をかき集めてきて最小のReact+Redux構成を作ってみました。

# ソースコード
```js:index.jsx
import React, { Component } from "react";
import { render } from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";


// React Component
class Container extends Component {
    render() {
        return (
            <div>
                <button onClick={ e => {
                    this.props.dispatch (
                        // ReducerにActionをディスパッチする
                        { type: "INCREMENT" }
                    );
                    console.log("pushed button");
                }}>
                    button
                </button>
                <div>
                    { this.props.value }
                </div>
            </div>
        );
    }
};
// NewComponent = connect(Componentからdispatchされたアクション) (Component)
const App = connect(
    state => state
)(Container);


// Reducer
const reducer = (state = { value: 0 }, action) => {
    // Componentの中でディスパッチされたActionがaction変数に入ってくる
    // action = { type: "INCREMENT" }
    switch (action.type) {
        case "INCREMENT":
            // valueに+1して返す
            return Object.assign({}, { value: state.value + 1 });
        default:
            return state;
    }
}


// Reducerの戻り値を新しい状態（State）としてStoreで管理する
const store = createStore(reducer);


// Root Render
// ReduxのProviderコンポーネントで、Appコンポーネント
// （connect関数にComponentを渡して作成したNewComponent）をラップし、Storeを渡す
// （簡単に言えば）propsにStateが入る
render (
    <Provider store={ store }>
        <App />
    </Provider>,
    document.getElementById("root")
);
```

# やってること
画面にボタンと初期値「0」が表示され、ボタンを押すたびに数字がインクリメントされます。


# 解説

## import文
```js:import文
import React, { Component } from "react";
import { render } from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";
```

見ての通りですが、React・Redux・React-Reduxから必要なものをimportしています。
それぞれの使い方は後から出てくるので、そちらを見てください。

## React Component
```js:ReactComponent
class Container extends Component {
    render() {
        return (
            <div>
                <button onClick={ e => {
                    this.props.dispatch (
                        // ReducerにActionをディスパッチする
                        { type: "INCREMENT" }
                    );
                    console.log("pushed button");
                }}>
                    button
                </button>
                <div>
                    { this.props.value }
                </div>
            </div>
        );
    }
};
```

こちらはReact入門までやった人ならなんとなくわかるのではないでしょうか？
ES2015シンタックスであるclass構文を使っていますが、`React.createClass`と大体同じです。
同じくArrow functionsも使用していますが、こちらについては各自ググってください。（丸投げスタイル）
実行すると（大体）下記のようなDOMが生成されます。

```html:実行結果
<div>
    <button>button</button>
    <div>0</div>
</div>
```

JSXに書いてあった内容ほぼそのままですね。
（this.props.value == 0として書いてます。）

ただし、1箇所Reactではない（Redux成分を含む）箇所があります。

```js:Redux成分
<button onClick={ e => {
    this.props.dispatch (
        // ReducerにActionをディスパッチする
        { type: "INCREMENT" }
    );
}}>
```

この部分です。

コード内のコメントの通り、Actionのディスパッチを行なっています。
ボタンがクリックされたら（`onClick`）、`dispatch`関数を呼ぶようになっています。
`dispatch`関数の引数にAction（＝JavaScriptのオブジェクト）を渡すと、後述のReducerにActionが渡されます（ディスパッチされます）。

Actionにはtypeを含める必要があります。
このtypeはReducerで処理を分けるためにあるので、かぶらなければなんでもいいです。

## connect
`connect`関数は、React-Reduxの関数です。ReactとReduxを繋いでいます。

```js:connect関数
// NewComponent = connect(Componentからdispatchされたアクション) (Component)
const App = connect(
    state => state
)(Container);
```

Provider（後述）に渡されたStore（後述）を、自分が定義したReact Component（今回はContainerクラス）のthis.propsに入れています。
説明は最後の`render`でしたほうがわかりやすいので、ここではあまり説明しません。


## Reducer
```js:Reducer
// Reducer
const reducer = (state = { value: 0 }, action) => {
    // Componentの中でディスパッチされたActionがaction変数に入ってくる
    // action = { type: "INCREMENT" }
    switch (action.type) {
        case "INCREMENT":
            // valueに+1して返す
            return Object.assign({}, { value: state.value + 1 });
        default:
            return state;
    }
}
```

この関数は、2つの引数を受け取ります。

* state …… 現在のState
* action …… React ComponentからディスパッチされたAction

Reducerでは、「必要なデータ」と「現在のState」を使って「やりたいこと」を実行する処理です。
action内のtypeによって処理を分けます。

Actionというのは、「やりたいこと(type)」と「必要なデータ」をひとまとまりにしたものです。
「やりたいこと」をswitch文で判断して、適切な処理を実行します。
「やりたいこと」が終わると、新しいStateが出来上がります。

これが「Action + State => NewState」の正体です。

### (2016/06/06 修正・追記)
コメントで教えていただいたのですが、現在のstateから新しいstateを作成するので、(Redux的に)正しくは下記のようになります。

修正前
`return Object.assign({}, { value: action.value + 1 });`

修正後
`return Object.assign({}, { value: state.value + 1 });`

現在の状態はstateに持っているので、そちらの値を使用するのがいいようです。
`dispatch`関数でvalueを渡す必要がなくなり、より簡潔になりました。
（この修正により、サンプルコードの中で、Actionの「必要なデータ」はなくなりました。）

## createStore
```js:Store生成
// Reducerの戻り値を新しい状態（State）としてStoreで管理する
const store = createStore(reducer);
```

`createStore`関数はReduxの関数です。
上で説明したReducerによって作られたStateを、Store内で管理します。
よくわからないですが、Reduxではそういう決まりみたいです。

## render()
```js:render処理
// Root Render
render (
    <Provider store={ store }>
        <App />
    </Provider>,
    document.getElementById("root")
);
```

これもReactをやっている方なら大体わかるかと思います。
違うところは、Providerで`connect`関数によって作られたAppをくるんでいるところですね。

このProviderはReact-Redux成分で、前述した`connect`関数とセットで、ReactとReduxを繋ぐ役割があります。

データの流れは、

1. Providerのstoreに渡された値が、中のAppに渡る
1. Appに渡ってきたデータが`connect`関数に渡る
1. `connect`関数では、受け取った値をそのまま返す
1. すると、Containerのthis.propsにデータが入る
1. Container（React Component）内ではthis.propsから見ることができる

となります。

# 処理の流れ
自分の理解では、このソースの上から下に処理が流れていくイメージになります。
捉え方によっては、もしかしたら下から上になるかもしれないです。

# 最後に
あくまで自分の理解なので、間違っている部分や伝わりづらい部分があるかと思いますが、その点はご了承ください。
写経だけでなく、自分で作るって大事だなぁと思いました。（小並感）