web-dev-qa-db-fra.com

EventEmitter et abonné ES6 Syntaxe avec React Native

J'essaie d'implémenter une relation EventEmitter/Subscriber entre deux composants dans une classe native React. J'ai vu référencé les documents suivants:

Ces solutions sont adéquates pour ce que j'essaie d'accomplir, cependant, elles prennent la peine d'utiliser l'utilisation de mixins: [Subscribable.Mixin] sur le composant récepteur pour fonctionner correctement avec Subscriber. Malheureusement, j'utilise ES6 et étends mes classes à partir de Component donc je ne peux pas utiliser cette syntaxe mixin.

Ma question est: comment puis-je implémenter les solutions ci-dessus dans ES6 sans utiliser de mixins?

16
Adam Jakiela

Vous n'avez pas besoin de mixins pour utiliser EventEmitters.

Démo simple:

import EventEmitter from 'EventEmitter';

let x = new EventEmitter();

function handler(arg) {
    console.log(`event-name has occurred! here is the event data arg=${JSON.stringify(arg)}`);
}

x.addListener('event-name', handler);

x.emit('event-name', { es6rules: true, mixinsAreLame: true });

La signature complète de addListener prend trois arguments:

EventEmitter.addListener(eventName, handler, handlerContext)

Dans un composant React, vous souhaiterez probablement utiliser cet argument de contexte, afin que le gestionnaire puisse être une méthode de classe au lieu d'une fonction en ligne et conserver toujours this == component instance. Par exemple.:

componentDidMount() {
    someEmitter.addListener('awesome', this.handleAwesomeEvents, this);
    // the generalist suggests the alternative:
    someEmitter.addListener('awesome', this.handleAwesomeEvents.bind(this));
}

handleAwesomeEvents = (event) => {
    let awesomeness = event.awesomeRating;

    // if you don't provide context in didMount,
    // "this" will not refer to the component,
    // and this next line will throw
    this.setState({ awesomeness });
};

FYI: J'ai obtenu cela en regardant l'implémentation décidément peu magique de l'infâme mixin Subscriptable . Les résultats de recherche Google sont essentiellement une chambre d'écho de la démo basée sur un mixin unique de Ramsay.

P.S. En ce qui concerne l'exposition de cet émetteur à un autre composant, le composant propriétaire fournirait probablement une fonction pour recevoir la référence de l'émetteur, et le composant qui crée l'émetteur exécuterait alors conditionnellement cet accessoire avec l'émetteur.

// owner's render method:
<ThingThatEmits
    onEmitterReady={(emitter) => this.thingEmitter = emitter}
/>

// inside ThingThatEmits:
componentDidMount() {
    this.emitter = new EventEmitter();

    if(typeof this.props.onEmitterReady === 'function') {
        this.props.onEmitterReady(this.emitter);
    }
}
30
Tom

J'ai pu obtenir une solution de contournement avec react-mixin . Je ne sais pas à quel point c'est correct, mais cela fonctionne sans aucune modification. La clé ajoute reactMixin(DetailView.prototype, Subscribable.Mixin); après la définition de classe.

En partant de l'exemple flottant pour EventEmitter et Subscribable:

'use strict';

var reactMixin = require('react-mixin');
var React = require('react-native');
var EventEmitter = require('EventEmitter');
var Subscribable = require('Subscribable');

var {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    NavigatorIOS
} = React;

class MainView extends Component {
    constructor(props){
      super(props);
      this.EventEmitter = new EventEmitter();
    }

    somethingHappenedFunction(){
      this.EventEmitter.emit("update_event", { message: "hello from up here"});
    }

    //rest of the class
}

class DetailView extends Component {
   componentDidMount(){
     this.addListenerOn(this.props.events, 'update_event', this.miscFunction);
   }

   miscFunction(args) {
    console.log("message: %s", args.message);
   }

   //rest of the class
}
reactMixin(DetailView.prototype, Subscribable.Mixin);
1
georges