Синтаксис EventEmitter и Subscriber ES6 с реакцией

Я пытаюсь реализовать связь EventEmitter/Subscriber между двумя компонентами в ответном родном классе. Я видел ссылки на следующие материалы:

Эти решения адекватны тем, что я пытаюсь выполнить, однако они требуют, чтобы использование mixins: [Subscribable.Mixin] на принимающем компоненте работало правильно с Subscriber. К сожалению, я использую ES6 и расширяю свои классы из Component, поэтому я не могу использовать этот синтаксис mixin.

Мой вопрос: как я могу реализовать вышеупомянутые решения в ES6 без использования mixins?

Ответ 1

Вам не нужны миксины для использования EventEmitters.

Простая демонстрация:

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

Полная подпись для addListener принимает три аргумента:

EventEmitter.addListener(eventName, handler, handlerContext)

В реагирующем компоненте вы, скорее всего, захотите использовать этот контекстный аргумент, чтобы обработчик мог быть методом класса вместо встроенной функции и по-прежнему сохранять this == component instance. Например:.

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: Я получил это от взгляда на явно неважную реализацию печально известного Подписываемого mixin. Результаты поиска в Google - это, в основном, эхо-камера демо-версии, основанной на одном микшинге от Ramsay.

P.S. Поскольку выставляя этот эмиттер другому компоненту, я бы, вероятно, обладал бы компонентом-обладателем функции для получения ссылки эмиттера, а компонент, который создает эмиттер, затем условно выполнил бы эту опору с эмиттером.

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

Ответ 2

Мне удалось найти временное решение с react-mixin. Не уверен, насколько это правильно, но он работает без каких-либо изменений. Ключ добавляет reactMixin(DetailView.prototype, Subscribable.Mixin); после определения класса.

Отключение примера, который перемещается для EventEmitter и Подписываемых:

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