店舗が独自の状態を維持し、そうすることでネットワークおよびデータストレージサービスを呼び出すことができる場合...その場合、アクションは単なるメッセージ通行人であり、
-または-
...ストアはアクションからの不変データの愚かな受信者である必要がありますか(そしてアクションは外部ソース間でデータをフェッチ/送信するものですか?このインスタンスのストアはビューモデルとして機能し、それらを集約/フィルタリングできますアクションによってフィードされた不変データに独自の状態ベースを設定する前のデータ。
それはどちらかでなければならないように思われます(両方の組み合わせではなく)。もしそうなら、なぜ一方が他方よりも優先/推奨されるのですか?
フラックスパターンが両方の方法で実装されていることを確認しました。両方を実行した後(最初は前者のアプローチを使用)、ストアはアクションからのデータのバカな受信者であり、書き込みの非同期処理はアクションクリエーター。 ( 非同期読み取りは異なる方法で処理できます 。)私の経験では、これにはいくつかの利点があります。
ストアは完全に同期します。これにより、ストアロジックの追跡が非常に簡単になり、テストが非常に簡単になります。特定の状態でストアをインスタンス化して送信するだけです。アクション、および状態が予想どおりに変更されたかどうかを確認します。さらに、流動的なコア概念の1つは、カスケードディスパッチを防止し、複数のディスパッチを一度に防止することです。ストアが非同期処理を行う場合、これは非常に困難です。
すべてのアクションディスパッチはアクションクリエーターから発生します。ストアで非同期操作を処理し、ストアのアクションハンドラーの同期を維持する場合フラックスのシングルディスパッチ保証を取得するには、ストアは非同期処理に応じて追加のSUCCESSおよびFAILアクションを起動する必要があります。これらのディスパッチをアクションクリエーターに配置すると、代わりにアクションクリエーターとストアのジョブを分離するのに役立ちます。さらに、アクションがどこからディスパッチされているかを把握するためにストアロジックを掘り下げる必要はありません。この場合の典型的な非同期アクションは次のようになります(使用しているフラックスのフレーバーに基づいてdispatch
呼び出しの構文を変更します):
someActionCreator: function(userId) {
// Dispatch an action now so that stores that want
// to optimistically update their state can do so.
dispatch("SOME_ACTION", {userId: userId});
// This example uses promises, but you can use Node-style
// callbacks or whatever you want for error handling.
SomeDataAccessLayer.doSomething(userId)
.then(function(newData) {
// Stores that optimistically updated may not do anything
// with a "SUCCESS" action, but you might e.g. stop showing
// a loading indicator, etc.
dispatch("SOME_ACTION_SUCCESS", {userId: userId, newData: newData});
}, function(error) {
// Stores can roll back by watching for the error case.
dispatch("SOME_ACTION_FAIL", {userId: userId, error: error});
});
}
さまざまなアクションで複製される可能性のあるロジックは、個別のモジュールに抽出する必要があります。この例では、そのモジュールはSomeDataAccessLayer
になり、実際のAjaxリクエストを処理します。
必要なアクション作成者は少なくなります。これは大したことではありませんが、持っておくといいです。 #2で説明したように、ストアに同期アクションディスパッチ処理がある場合(およびそうする必要がある場合)、非同期操作の結果を処理するために追加のアクションを起動する必要があります。アクションクリエーターでディスパッチを行うことは、単一のアクションクリエーターが非同期データアクセス自体の結果を処理することで3つのアクションタイプすべてをディスパッチできることを意味します。
この質問をFacebookの開発者にツイートしたところ、Bill Fisherから得た答えは次のとおりです。
ユーザーのUIとの対話に応答するとき、アクションクリエーターメソッドで非同期呼び出しを行います。
しかし、ティッカーまたはその他の人間以外のドライバーがいる場合は、ストアからの呼び出しの方が効果的です。
重要なことは、エラー/成功コールバックでアクションを作成し、データが常にアクションから発生するようにすることです
ストアは、データの取得、ストアのデータが更新されたことをコンポーネントに通知するなど、すべてを行う必要があります。なぜですか?アクションは軽量で、使い捨てで、重要な動作に影響を与えずに交換できるためです。すべての重要な動作と機能はストアで発生します。これにより、非常に似ているが異なる2つのアクションでコピーされる動作の重複も防止されます。店はあなたの単一の真実の(処理する)源です。
従来の「anchor:clicked」というイベントがあるように、アクションは基本的にオブジェクトに変換されるイベント文字列ですが、FluxではAnchorActions.Clickedとして定義されます。それらは「ダム」でさえあり、ほとんどの実装は、リスニングしているストアにイベントを実際にディスパッチするための別個のDispatcherオブジェクトを持っています。
個人的には、個別のDispatcherオブジェクトがなく、Actionオブジェクトが自身でディスパッチを行うRefluxのFluxの実装が好きです。
編集:FacebookのFluxは実際に「アクションクリエーター」を取得するため、スマートアクションを使用します。また、ストアを使用してペイロードを準備します。
完了時のコールバックは、フェッチされたデータをペイロードとして、今回は新しいアクションをトリガーします。
だから私はそれがより良い解決策だと思います。
「ダム」アクションを支持する議論を提供します。
アクションにビューデータを収集する責任を負うことにより、アクションをビューのデータ要件に結び付けます。
対照的に、ユーザーのintent、またはアプリケーションの状態遷移を宣言的に記述するジェネリックアクションは、そのアクションに応答するストアがインテントをビューに特化した状態に変換できるようにします購読しました。
これは、より多くの、しかしより小さく、より専門的なストアに役立ちます。私はこのスタイルを主張します
ストアの目的は、ビューにデータを提供することです。 「アクション」という名前は、その目的がアプリケーションの変更を記述することであることを示唆しています。
ウィジェットを既存のダッシュボードビューに追加する必要があるとします。このビューには、バックエンドチームが展開したばかりのいくつかの派手な新しい集計データが表示されます。
「スマート」アクションでは、「refresh-dashboard」アクションを変更して、新しいAPIを使用する必要があります。ただし、抽象的な意味での「ダッシュボードの更新」は変更されていません。ビューのデータ要件が変更されました。
「ダム」アクションでは、新しいウィジェットが使用する新しいストアを追加し、「refresh-dashboard」アクションタイプを受信すると、新しいデータのリクエストを送信し、それを公開するように設定できます。準備ができたら、新しいウィジェット。ビューレイヤーがより多くのまたは異なるデータを必要とする場合、私が変更するのはそのデータのソースであるストアです。
gaeronの flux-react-router-demo には、「正しい」アプローチの便利なバリエーションがあります。
ActionCreatorは外部APIサービスからプロミスを生成し、プロミスと3つのアクション定数をプロキシ/拡張ディスパッチャーのdispatchAsync
関数に渡します。 dispatchAsync
は常に最初のアクションをディスパッチします。 「GET_EXTERNAL_DATA」。Promiseが返されたら、「GET_EXTERNAL_DATA_SUCCESS」または「GET_EXTERNAL_DATA_ERROR」をディスパッチします。
Bret Victorの有名なビデオ Inventing on Principle で見られるものに匹敵する開発環境をいつか実現したい場合は、データ構造内のアクション/イベントの単なる投影であるダムストアを使用する必要があります、副作用なし。 Redux のように、ストアが実際に同じグローバルな不変データ構造のメンバーである場合にも役立ちます。