web-dev-qa-db-fra.com

Émettre et gérer des événements mondiaux avec react

Je m'amuse un peu à réagir pour créer un "bouton Ajouter au panier". Voici mon code.

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>
    );
  }
});

Ce qui m'intrigue, c'est ce gestionnaire d'ajax. Je suis à peu près sûr que le point essentiel de la réaction est l'interopérabilité entre les composants, sauf que je ne sais pas où diriger ces événements. J'imaginais deux composants différents, tels qu'un indicateur de nombre de paniers en cas de succès ou une alerte d'erreur en cas d'échec, mais je ne sais pas exactement comment y accéder. Est-ce tout l'intérêt de les répartiteurs de flux ?

17
ThomasReggi

Oui, cela fait certainement partie des arguments des répartiteurs de Flux - ou de tout émetteur d'événement que vous souhaitez utiliser.

Avant de vous engager dans cette voie, il est très facile de simplement transmettre des gestionnaires d'événements comme accessoires sans utiliser Flux ou des émetteurs d'événements personnalisés, comme vous le feriez avec les gestionnaires onSubmit, onClick, etc. pour des éléments DOM normaux. Ensuite, demandez au parent de définir l'état et de le communiquer éventuellement à d'autres enfants (via des accessoires).

Donc, dans ce cas, imaginez un composant parent qui traite des événements:

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} />
    )
  }
})

Et ensuite, la partie pertinente de votre composant ProductPurchase serait:

  success: function(data) {
    this.props.onCartAdded(data)
  }.bind(this),
  error: function(xhr, status, err) {
    this.props.onError(err)
  }.bind(this)

Un exemple plus complexe consisterait à transmettre le résultat à un autre composant enfant - mais laissez à nouveau le soin au parent de gérer ceci:

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>
    )
  }
})

De cette manière, les composants sont découplés les uns des autres - et les données/fonctions ne peuvent être transmises que par un contrat clair (accessoires).

Ce style simple de gestion des événements est beaucoup plus explicite et plus facile à déboguer - je ne recourrais donc à une architecture de style Flux que si votre application devient vraiment complexe et/ou si vous avez beaucoup de composants qui doivent tous communiquer entre eux. autre de manière complexe.

16
Michael Hart

Flux est utilisé pour découpler les constructions de programmation (y compris les appels AJAX).

Voici le schéma de la Flux Docs

Flux Architecture Diagram

Dispatcher dans l'architecture de Flux reste toujours dans la portée globale. Ainsi, toute opération impliquée avec le répartiteur se produit toujours dans la portée globale. En outre, le répartiteur et le système d'événements présentent une légère différence: le système d'événements enregistre toujours les rappels liés à un événement spécifique, mais dans le cas des répartiteurs, tous les rappels sont liés à tous les événements.

Comment utiliser Dispatcher? (Approche simplifiée sans utiliser Stores et ActionCreators)

  1. Si d'autres parties de l'application sont affectées par cet appel AJAX, vous ne devez pas effectuer cet appel AJAX à partir de ce composant, mais déplacez l'appel AJAX dans un nouveau fichier et une fonction. Par exemple, en utilisant CommonJS,

    // CartApiUtils.js
    module.exports = {
        addToCart: function(item){
            // AJAX call
        }
    }
    
  2. Créez un AppDispatcher (qui est commun dans toute l'application) à l'aide de la classe Dispatcher de Flux

    var appDispatcher = new Dispatcher();
    
  3. Dans la fonction addToCart (), en cas de succès de la réponse AJAX, distribuez un événement à l'aide de AppDispatcher:

    appDispatcher.dispatch({
        actionType: 'cart.newItemAdded',
        data: dataFromAjax
    });
    
  4. Dans votre application, où que vous souhaitiez utiliser cet événement, vous pouvez simplement enregistrer une fonction pour la dissociation.

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

C'est une approche simplifiée. Dans une structure plus normalisée et une application plus grande, vous devez utiliser Stores (qui ressemble à la couche modèle de MVC, mais pas identique) et ActionCreator où toute interaction sur la couche vue est une action de l'utilisateur et toute réponse du AJAX call devient également une action du serveur.

La règle Thumb est la suivante: les vues doivent être renseignées (ou mises à jour) à partir des magasins et les magasins doivent être mis à jour pour les événements Dispatcher.

5
Sanket Sahu

Qu'en est-il de l'utilisation de "react-global-events" de npm?

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

2