baobab-reactを使って軽量fluxを回す


reactでfluxやってるとあのサイクルを回すのが面倒くさくなりませんか？僕はなりました。
そこでbaobab-reactです。

```
                                 ┌────────────────────┐
                   ┌──────────── │    Central State   │ ◀───────────┐
                   │             │    (Baobab tree)   │             │
                   │             └────────────────────┘             │
                Renders                                          Updates
                   │                                                │
                   │                                                │
                   ▼                                                │
        ┌────────────────────┐                           ┌────────────────────┐
        │        View        │                           │       Actions      │
        │ (React Components) │  ────────Triggers───────▶ │     (Functions)    │
        └────────────────────┘                           └────────────────────┘
```

https://github.com/Yomguithereal/baobab-react/blob/master/docs/higher-order.md#actions

1周がこんな感じで回っています。
1本のstate treeがあり、そこから一意に定まるviewがあり、viewがactionを発行し、actionはstate treeを更新する。
まさに求めていた軽量fluxって感じですごく良かったです。

例としてしょうもないカウンターを作ってみます

![screenshot 2016-03-20 0.02.26.png](https://qiita-image-store.s3.amazonaws.com/0/22102/12a9b78c-2eab-80f0-9440-cfc840458f6a.png "screenshot 2016-03-20 0.02.26.png")


## install

`npm i -S baobab baobab-react@1.0.0`

~~現在最新の`2.0.0rc`は上手くimportが出来ないため一個前のバージョンを指定しています。~~
2016-04-01追記
_現在の安定版は`1.0.1`です。_

## state tree

アプリケーションの全状態を管理する1本のstate treeを作ります。

```js:tree.js
import Baobab from "baobab";

export default new Baobab({
  counter: 0
});
```

こんな感じでstate treeとなるobjectを渡したbaobabのインスタンスをexportします。

## root component

```js:index.js
import React from "react";
import {render} from "react-dom";
import {root} from 'baobab-react/higher-order';
import tree from "./tree";
import App from "./app";

const RootedApp = root(App, tree);
render(
  <RootedApp />,
  document.getElementById("app")
);
```

こんな感じで、ルートとなるコンポーネントはbaobab-reactのroot関数でラップした物を使います。

2016-04-01追記
_現在betaの`2.0.0`では`higher/order`関数のシグネチャが変更されて、Componentとcursorの引数が逆になるようです。
`root(Component, tree)` → `root(tree, Component)`_

## branch component

全てのコンポーネントはbaobab-reactのbranchでラップしたものを使うようにします。

```js:app.js
import React from "react";
import {branch} from "baobab-react/higher-order";

export default branch(class App extends React.Component {
  handleClickPlus() {
    this.props.actions.addCount(1);
  }

  handleClickMinus() {
    this.props.actions.addCount(-5);
  }

  render() {
    return (
      <div>
        <h1>count: {this.props.counts}</h1>
        <button onClick={() => this.handleClickPlus()}>plus 1</button>
        <button onClick={() => this.handleClickMinus()}>minus 5</button>
      </div>
    );
  }
}, {
  actions: {
    addCount: (tree, value) => {
      const counter = tree.get(["counter"]);
      tree.set(["counter"], counter + value);
    }
  },
  cursors: {
    counts: ["counter"]
  }
});
```

2016-04-01追記
_こちらもroot関数と同じでComponentとcursorの引数が逆になっています。
`branch(App, Component)` → `root(cursors, Component)`_

branchは`branch(コンポーネントクラス, {actions: {}, cursors: {}})`という感じで作成します。
第二引数の`actions`にはそのコンポーネントで使うアクション関数を渡します。keyの名前で`props.actions`以下にアクション関数が登録されます。ここでactionを登録しておくとaction関数の第一引数に`tree`がインジェクションされるようになるので、好きなようにstate treeをいじることが出来るようになります。
第二引数の`cursors`は`tree`の参照を示していて配列でパスを渡すと`tree`の該当する値をkeyの名前で`props`においてくれます。

あとはbrowserifyとかbabelifyとかしてhtmlで読み込んでやればokです。
今はactionを個別に作っていますがactions.jsみたいなところから読み込んでやったり、BaseComponentを作ってそこでactionsは定義してしまったりとお好きなようにいい感じにしてください。

以上。