ReactJS + facebook/flux でカウンターのサンプル


## 目的
[Web+DB Press Vol.87 の Flux の記事](http://gihyo.jp/magazine/wdpress/archive/2015/vol87) が素晴らしかったので、[facebook/flux](https://github.com/facebook/flux) で書き換えてみた。
（記事では [fluxxor](http://fluxxor.com/)）

ちなみに雑誌のサンプルコードは [こちらの「Emerging Web Technology研究室」](http://gihyo.jp/magazine/wdpress/archive/2015/vol87/support)

下記todoサンプルを参考にした
- [https://github.com/facebook/flux/tree/master/examples/flux-todomvc]


## ファイル構成

```
.
├── dest
│   └── app.js
├── index.html
├── package.json
└── src
    ├── app.jsx
    └── app_dispatcher.js
```

## package

reactify ではなく babelify を使う

```pacage.json
{
  "devDependencies": {
    "babelify": "^6.1.2",
    "browserify": "^10.2.4",
    "watchify": "^3.2.3"
  },
  "scripts": {
    "watch": "watchify -t babelify src/app.jsx -o dest/app.js -v"
  },
  "dependencies": {
    "flux": "^2.0.3",
    "keymirror": "^0.1.1",
    "object-assign": "^3.0.0",
    "react": "^0.13.3"
  }
}

```

```
$ npm install
$ npm run watch
```

## code

```src/app.jsx
var EventEmitter = require('events').EventEmitter;
var React = require('react');
var assign = require('object-assign');
var keyMirror = require('keymirror');

var AppDispatcher = require('./app_dispatcher');

var CounterConstants = keyMirror({
    UPDATE_COUNTER: null
});


// Store
var CHANGE_EVENT = 'change';
var counter = 0;

var CounterStore = assign({}, EventEmitter.prototype, {
    getCounter: function() {
        return counter;
    },
    emitChange: function() {
        this.emit(CHANGE_EVENT);
    },
    addChangeListener: function(callback) {
        this.on(CHANGE_EVENT, callback);
    },
    onUpdateCounter: function(value) {
        counter += value;
    }
});

AppDispatcher.register(function(action) {
    switch(action.actionType) {
        case CounterConstants.UPDATE_COUNTER:
            CounterStore.onUpdateCounter(action.value);
            CounterStore.emitChange();
            break;
        default:
            // no op
    }
});


// Action
var CounterActions = {
    plusCounter: function() {
        AppDispatcher.dispatch({
            actionType: CounterConstants.UPDATE_COUNTER,
            value: 1
        });
    },
    minusCounter: function() {
        AppDispatcher.dispatch({
            actionType: CounterConstants.UPDATE_COUNTER,
            value: -1
        });
    }
};


// View
function getCounterState() {
    return {
        value: CounterStore.getCounter()
    };
}

var CounterAppView = React.createClass({
    getInitialState: function() {
        return getCounterState();
    },
    componentDidMount: function() {
        CounterStore.addChangeListener(this.onChange);
    },
    render: function() {
        return (
            <div>
                <span>count: {this.state.value}</span>
                <CounterView />
            </div>
        );
    },
    onChange: function() {
        this.setState(getCounterState());
    }
});

var CounterView = React.createClass({
    render: function() {
        return (
            <div>
                <div>
                    <button onClick={this.onClickPlus}>+1</button>
                    <button onClick={this.onClickMinus}>-1</button>
                </div>
            </div>
        );
    },
    onClickPlus: function() {
        CounterActions.plusCounter();
    },
    onClickMinus: function() {
        CounterActions.minusCounter();
    }
});

React.render(
    <CounterAppView />,
    document.getElementById('app-container')
);
```

```src/app_dispatcher.js
var Dispatcher = require('flux').Dispatcher;

module.exports = new Dispatcher();
```

```index.html
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Flux</title>
    </head>
    <body>
        <div id="app-container"></div>

        <script src="dest/app.js"></script>
    </body>
</html>
```

## 表示

```
$ python -m SimpleHTTPServer 8000
```

- http://localhost:8000


![スクリーンショット 2015-07-03 0.20.12.png](https://qiita-image-store.s3.amazonaws.com/0/41656/3fb3784f-2d3e-965e-eff8-33d1bc7e8d04.png "スクリーンショット 2015-07-03 0.20.12.png")


## 続き

- [ES6 の class などを使って書き換えてみた](http://qiita.com/cortyuming/items/bf24a087b4831ffa20f8)


## 感想

- ES6で書き換えようかと思ったけどツラそう...
- flux のライブラリは何を使うのがいいのやら...


## 参考

- http://gihyo.jp/magazine/wdpress/archive/2015/vol87
- https://github.com/facebook/flux/