「カートに追加ボタン」を作成するために反応して少し遊んでいます。これが私のコードです。
var ProductPurchase = React.createClass({
handleSubmit: function(e){
e.preventDefault();
$.ajax({
url: "/cart/add.js",
method: "post",
dataType: "json",
data: {
"id": this.props.variantId,
"quantity": this.props.quantity,
},
success: function(data) {
// emit cart added event
}.bind(this),
error: function(xhr, status, err) {
// emit error event (cart added)
}.bind(this)
});
},
getDefaultProps: function(){
return {
quantity: 1,
variantId: 231634908,
buttonText: "Add to cart"
}
},
render: function() {
return (
<div className="productPurchase">
<form action="/cart/add" method="post" enctype="multipart/form-data" onSubmit={this.handleSubmit}>
<input type="hidden" name="quantity" value={ this.props.quantity } />
<input type="hidden" name="id" value={ this.props.variantId } />
<button type="submit">{this.props.buttonText}</button>
</form>
</div>
);
}
});
私が興味を持っているのは、このajaxハンドラです。これらのイベントをどこから導くかわからないことを除いて、反応のポイントはコンポーネント間の相互運用性であると確信しています。成功した場合はカートカウントインジケーター、失敗した場合はエラーアラートなど、いくつかの異なるコンポーネントを想像できますが、これらを活用する方法は正確にはわかりません。これが fluxのディスパッチャ の要点ですか?
はい、それは確かにFluxのディスパッチャのポイントの一部です-またはあなたが使用したいイベントエミッタ。
ただし、そのパスをたどる前に、Fluxやカスタムイベントエミッターを使用せずに、イベントハンドラーを小道具として渡すことは非常に簡単です。通常のonSubmit
、onClick
などのハンドラーと同様です。 DOM要素。次に、親に状態の設定を処理させ、他の子に(小道具を介して)潜在的に通信します。
したがって、この場合、イベントを処理する親コンポーネントを想像してください。
var RootComponent = React.createClass({
handleCartAdded: function(cart) {
console.log('Got a new cart: ' + cart);
}
handleError: function(err) {
console.error(err)
}
render: function() {
return (
<ProductPurchase onCartAdded={this.handleCartAdded} onError={this.handleError} />
)
}
})
そして、ProductPurchase
コンポーネントの関連部分は次のようになります。
success: function(data) {
this.props.onCartAdded(data)
}.bind(this),
error: function(xhr, status, err) {
this.props.onError(err)
}.bind(this)
より複雑な例は、結果を別の子コンポーネントに渡すことです。ただし、これを管理するために親に任せます。
var RootComponent = React.createClass({
handleCartAdded: function(cart) {
this.setState({cart: cart})
}
handleError: function(err) {
console.error(err)
}
render: function() {
return (
<div>
<ProductPurchase onCartAdded={this.handleCartAdded} onError={this.handleError} />
<CartSummary cart={this.state.cart} />
</div>
)
}
})
このようにして、コンポーネントは相互に分離され、データ/機能は明確な契約(小道具)によってのみ渡すことができます。
この単純なスタイルのイベント処理は、はるかに明示的でデバッグが容易です。したがって、アプリが本当に複雑になったり、それぞれと通信する必要のあるコンポーネントがたくさんある場合は、Fluxスタイルのアーキテクチャにのみ頼るでしょう。他の複雑な方法。
フラックスは、プログラミング構成要素(AJAX呼び出しを含む)を分離するために使用されます。
Flux Docs の図を次に示します
FluxアーキテクチャのDispatcherは、常にグローバルスコープのままです。そのため、ディスパッチャに関連する操作は常にグローバルスコープで発生します。また、ディスパッチャとイベントシステムにはわずかな違いがあり、イベントシステムは常に特定のイベントにバインドされたコールバックを登録しますが、ディスパッチャの場合、すべてのコールバックはすべてのイベントにバインドされます。
Dispatcherの使用方法(StoresおよびActionCreatorsを使用しない単純化されたアプローチ)
アプリケーションの他の部分がこのAJAX呼び出しの影響を受ける場合、このコンポーネントからこのAJAX呼び出しを行うのではなく、AJAX呼び出しを新しいファイルと関数に移動してください。たとえば、CommonJSを使用して、
// CartApiUtils.js
module.exports = {
addToCart: function(item){
// AJAX call
}
}
Fluxの Dispatcherクラス を使用してAppDispatcher(アプリケーション全体で共通)を作成します
var appDispatcher = new Dispatcher();
AddToCart()関数で、成功したAJAX応答で、AppDispatcherを使用してイベントをディスパッチします。
appDispatcher.dispatch({
actionType: 'cart.newItemAdded',
data: dataFromAjax
});
アプリでは、このイベントを使用する場所に関係なく、dispacherに関数を登録できます。
appDispatcher.register(function(payload){
if(payload.actionType === 'cart.newItemAdded'){
// payload.data contains the data
}
});
これは単純化されたアプローチです。より正規化された構造と大きなアプリでは、ストア(MVCのモデルレイヤーのようなものですが、同一ではありません)とActionCreatorを使用する必要があります。アクションレイヤーでは、ユーザーによるアクションとAJAX呼び出しは、サーバーからのアクションにもなります。
経験則では、ビューはストアから移入(または更新)する必要があり、ストアはDispatcherイベントで更新する必要があります。
Npmの「react-global-events」を使用するのはどうですか?