JavaScript
flux
reactjs
marty

良さ気なFlux実装、Marty.js個人的まとめ

More than 3 years have passed since last update.

2015/12/03 追記: MartyのReadmeより

Martyはもうメンテをしないので、reduxかaltを使う事が推奨されるようです。ありがとうMarty。

以下過去の記事内容


Flux Comparisonで色々眺めていたり、twitterを追っかけていたり自分で触ってみたりして、

Marty.jsが個人的に本当に良い気がしている。


Martyの特徴


作者と質問者の会話より

ユーザーとのこんなやりとりがあり、Martyの特徴が要約されているのかなと思ったのでテキトーな意訳として載せておく。


https://news.ycombinator.com/item?id=8923245

質問:fluxxorと何が違うのか?

回答:

他のFlux実装は、Fluxっぽいデータフェッチ(APIなどのことだと思う)なヘルパーが無い。コンポーネントとのストアのバインディングのボイラープレートの方向に向かっている。あとデバッグ機能。他のはあんまりデバッグ機能拡充してない

Martyは下記のことを助ける


  • コールバック無しの非同期データフェッチ

  • viewのためのState Mixin

  • Chrome Extensionのデバッガー


ということでこの辺りが特徴らしい


  • コールバック無しの非同期データフェッチ

  • viewのためのState Mixin

  • Chrome Extensionのデバッガー


Facebook Fluxとの対比

公式の図とMartyにおけるAPIの対応がどうなっているかをまとめる

だいぶ雑な図だけど僕の中でこんなイメージ。

marty.png


対応表

Flux
Marty

Web API Utils
State Source

Action Creators
Action Creators

Store
Store

Change Events
Store Queries
State Mixin

Dispatcher
Constants(*)

Callbacks
Constants(*)

(*) DispatcherとConstantsなどは、隠蔽している関係などで、直接1:1ではなくなっている、このへんは自分なりの理解。


有益なサンプル

そもそもまだそんなに見つけられなかったのだけど、見るならこのへん


各機能のざっくり説明など

だいたいコードとかは公式サンプル持ってきたりしています


State Source

WebAPIUtilに相当する、データ取得の実装を巻き取る層。

Martyの目玉機能の一つだし僕が「これいいなあ」となった部分の一つ。


UserAPI.js

var UserAPI = Marty.createStateSource({

type: 'http',
baseUrl: 'http://foo.com',
getUsers: function () {
// github/fetch 形式での取得(後述)
return this.get('/users').then(function (res) {
// 完了したら、ActionCreatorを呼ぶ
SourceActionCreators.receiveUsers(res.body);
});
},
createUser: function (user) {
return this.post('/users', { body: user });
}
});

こんな感じでthis.getなどで通信処理ができる。

HTTPの通信処理はisomophic-fetchが使われているようなので何も考えずにpromiseな感じで書いていける。

またHTTPだけでなくLocal StorageやSession Storageへのアクセスヘルパーも用意してくれている模様(未調査)


Constants

このあたりからは他のflux実装とわりと似てくる。


Constants.js

var Constants = Marty.createConstants([

'RECEIVE_USERS',
'DELETE_USER'
]);


  • ほかのflux実装にもよくあるconstantとほぼ一緒。

  • Actionとして発火される定数を定義

  • オブジェクトとしてconstantを階層化することもできる

  • 各Constantsが、Actionを発火することのできるAction Creatorの関数となっている(という認識)


  • {Action Type}_STARTING{Action Type}_DONE{Action Type}_FAILEDなど、特定の接尾辞のついた定義をすることによってPromiseがらみの処理ができるらしい(未調査)




Action Creators

これもわりと他にもよくある実装。


  • ちょっとこれは理解するの時間がかかった。

  • 言ってしまえばConstantsから生まれるAction Creatorの集合体。


  • action.rollback()などで失敗時にロールバックもできるらしい。(未調査)

  • 体感としてこのあたりどうしても若干冗長に感じる


ActionCreatro.js

var UserConstants = Marty.createConstants(["UPDATE_EMAIL"]);

var UserActionCreators = Marty.createActionCreators({
updateEmail: UserConstants.UPDATE_EMAIL(function (userId, email) {
this.dispatch(userId, email) //例
})
});

UserActionCreators.updateEmail(123, "foo@bar.com");



  • また注意点として、この部分の処理は()=>なarrow functionを利用するとthisのスコープが変更されてしまうので、避けるようにとのアナウンスがある。


    • 個人的には余り気にならないが、がっかりする人いそうだ

    • 関連pull req




Stores


  • だいたい他のfluxと同等のStore


  • handlersの定義でConstantのAction Creatorを指定している。


  • handlersの定義は、複数のConstantsを受けたりとか色々複雑な指定ができる模様(未調査)




Store.js

var UsersStore = Marty.createStore({

displayName: 'Users',
handlers: {
addUser: Constants.RECEIVE_USER
},
getInitialState: function () {
return {};
},
addUser: function (user) {
this.state[user.id] = user;
this.hasChanged();
}
});


State Mixin


  • State <=> Component(ReactComponent)をつなぐ部分

  • 結構公式だと長いサンプルがあるが、単純にStoreとComponentをつなぐなら簡易に書ける


UserComponent.js

var UserState = Marty.createStateMixin(UserStore);

var UserComponent = React.createClass({
mixins : [UserState],
:
:
})



  • 上記は結構sugger syntaxっぽい気もするが、複数のStoreをListenしたりとか細かめに設定することも可能(未調査)


UserState.js

var UserState = Marty.createStateMixin({

listenTo: [UserStore, FooStore]
});


Debug機能

なんかまだうまく使えてないので未調査。


結論

Martyええぞ。