web-dev-qa-db-ja.com

Reactを使用したグローバルイベントの発行と処理

「カートに追加ボタン」を作成するために反応して少し遊んでいます。これが私のコードです。

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のディスパッチャ の要点ですか?

19
ThomasReggi

はい、それは確かにFluxのディスパッチャのポイントの一部です-またはあなたが使用したいイベントエミッタ。

ただし、そのパスをたどる前に、Fluxやカスタムイベントエミッターを使用せずに、イベントハンドラーを小道具として渡すことは非常に簡単です。通常のonSubmitonClickなどのハンドラーと同様です。 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スタイルのアーキテクチャにのみ頼るでしょう。他の複雑な方法。

17
Michael Hart

フラックスは、プログラミング構成要素(AJAX呼び出しを含む)を分離するために使用されます。

Flux Docs の図を次に示します

Flux Architecture Diagram

FluxアーキテクチャのDispatcherは、常にグローバルスコープのままです。そのため、ディスパッチャに関連する操作は常にグローバルスコープで発生します。また、ディスパッチャとイベントシステムにはわずかな違いがあり、イベントシステムは常に特定のイベントにバインドされたコールバックを登録しますが、ディスパッチャの場合、すべてのコールバックはすべてのイベントにバインドされます。

Dispatcherの使用方法(StoresおよびActionCreatorsを使用しない単純化されたアプローチ)

  1. アプリケーションの他の部分がこのAJAX呼び出しの影響を受ける場合、このコンポーネントからこのAJAX呼び出しを行うのではなく、AJAX呼び出しを新しいファイルと関数に移動してください。たとえば、CommonJSを使用して、

    // CartApiUtils.js
    module.exports = {
        addToCart: function(item){
            // AJAX call
        }
    }
    
  2. Fluxの Dispatcherクラス を使用してAppDispatcher(アプリケーション全体で共通)を作成します

    var appDispatcher = new Dispatcher();
    
  3. AddToCart()関数で、成功したAJAX応答で、AppDispatcherを使用してイベントをディスパッチします。

    appDispatcher.dispatch({
        actionType: 'cart.newItemAdded',
        data: dataFromAjax
    });
    
  4. アプリでは、このイベントを使用する場所に関係なく、dispacherに関数を登録できます。

    appDispatcher.register(function(payload){
        if(payload.actionType === 'cart.newItemAdded'){
            // payload.data contains the data
        }
    });
    

これは単純化されたアプローチです。より正規化された構造と大きなアプリでは、ストア(MVCのモデルレイヤーのようなものですが、同一ではありません)とActionCreatorを使用する必要があります。アクションレイヤーでは、ユーザーによるアクションとAJAX呼び出しは、サーバーからのアクションにもなります。

経験則では、ビューはストアから移入(または更新)する必要があり、ストアはDispatcherイベントで更新する必要があります。

5
Sanket Sahu

Npmの「react-global-events」を使用するのはどうですか?

https://www.npmjs.com/package/react-global-events

2