reactでfluxやってるとあのサイクルを回すのが面倒くさくなりませんか?僕はなりました。
そこでbaobab-reactです。
┌────────────────────┐
┌──────────── │ Central State │ ◀───────────┐
│ │ (Baobab tree) │ │
│ └────────────────────┘ │
Renders Updates
│ │
│ │
▼ │
┌────────────────────┐ ┌────────────────────┐
│ View │ │ Actions │
│ (React Components) │ ────────Triggers───────▶ │ (Functions) │
└────────────────────┘ └────────────────────┘
1周がこんな感じで回っています。
1本のstate treeがあり、そこから一意に定まるviewがあり、viewがactionを発行し、actionはstate treeを更新する。
まさに求めていた軽量fluxって感じですごく良かったです。
例としてしょうもないカウンターを作ってみます
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を作ります。
import Baobab from "baobab";
export default new Baobab({
counter: 0
});
こんな感じでstate treeとなるobjectを渡したbaobabのインスタンスをexportします。
root component
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でラップしたものを使うようにします。
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は定義してしまったりとお好きなようにいい感じにしてください。
以上。