私は現在、ReactJS に一般的に関連付けられているフラックス パターンを使用して、プロトタイプ アプリケーションに取り組んでいます。
Facebookフラックス/チャットの例では、 ThreadStoreとUnreadThreadStoreの 2 つのストアがあります。後者は、前者のコンテンツを同期的に読み取るgetAllメソッドを提供します。
派生ストアでの操作はコストがかかりすぎて同期的に実行できず、理想的には非同期プロセス (Web ワーカー、サーバー トリップ) に委任されるという問題が発生しました。これを解決するにはどうすればよいか考えています。
私の同僚は、ゲッターからプロミスを返すことを提案しています。
# MyView
componentDidMount: function () {
defaultState = { results: [] };
this.setState(defaultState);
DerivedStore.doExpensiveThing()
.then(this.setState);
}
私はこれに完全に満足していません。ビューはストアではなく変更の主な受信者であるため、パターンとの決別のように感じます。これは、私たちが検討してきた別の手段です。この方法では、ビューのマウント イベントが、派生データを更新する要求をディスパッチします (必要な場合)。
# DerivedStore
# =========================================================
state: {
derivedResults: []
status: empty <fresh|pending|empty>
},
handleViewAction: function (payload) {
if (payload.type === "refreshDerivedData") {
this.state.status = "pending"; # assume an async action has started
}
if (payload.type === "derivedDataIsRefreshed") {
this.state.status = "fresh"; # the async action has completed
}
this.state.derivedResults = payload.results || []
this.notify();
}
# MyAction
# =========================================================
MyAction = function (dispatcher) {
dispatcher.register(function (payload) {
switch (payload) {
case "refreshDerivedData":
doExpensiveCalculation()
.then(function(res) {
dispatcher.dispatch({
type: "derivedDataIsRefreshed",
results: res
})
})
);
}
});
};
# MyView
# =========================================================
MyView = React.createClass({
componentDidMount: function () {
if (DerivedStore.getState().status === "empty") {
Dispatcher.dispatch("refreshDerivedData");
}
},
getVisibility: function () {
return DerivedStore.getState().status === "pending" ? "is-visible" : ""
},
render: function () {
var state = DerivedStore.getState()
, cx = React.addons.classSet
, classes = cx({
"spinner-is-visible": state.status === "pending"
});
return <div {classes}>
<Spinner /> # only visible if "spinner-is-visible
<Results results={state.derivedResults}/> # only visible if not...
</div>;
}
});
# MyService
# =========================================================
# ensure derived data is invalidated by updates in it's source?
OriginalStore.addListener(function () {
setTimeout(function () {
dispatcher.dispatch({
type: "refreshDerivedData"
})
}, 0);
});
このアプローチで私が気に入っているのは、ビューが DerivedStore をビュー モデルとして扱い、この類のビューが主にビュー モデルの鮮度に関心があることです。しかし、私が懸念しているのは、ストアが同期しなくなる可能性です。
私の質問は次のとおりです。
- 約束のアプローチは受け入れられますか?
- 2番目のアプローチはより良い/より悪いですか?もしそうなら、なぜですか?
- この問題に対する既存の「標準的な」アプローチはありますか?
PS: このコードに基本的なリンティング エラーがある場合は申し訳ありません。私は過去 3 か月間 Coffeescript で作業しており、リンティング機能が破壊されました...