2016-04-21 32 views
12

Próbuję zaimplementować relację EventEmitter/Subscriber między dwoma komponentami w klasie macierzystej reagowania. Widziałem odwołuje następujących materiałów:Składnia EventEmitter i Subscriber ES6 z React Native

Rozwiązania te są adekwatne do tego, co staram się osiągnąć, jednak oni niepokoić wymagają użycia mixins: [Subscribable.Mixin] na elemencie odbiorczym do poprawnej pracy z Subscriber. Niestety, używam ES6 i rozszerzam moje klasy z Component, więc nie mogę używać tej składni mixin.

Moje pytanie brzmi: jak mogę wdrożyć powyższe rozwiązania w ES6 bez użycia mixins?

+0

Tutaj ktoś sugeruje użycie po prostu użyć „stary sposób” pisania części: http://hi-tips.tumblr.com/post/137014836571/use-eventemitter-for-calling-child-component -event Mam ten sam problem i chciałbym się dowiedzieć, czy jest jakiś właściwy sposób wykonania tego w ES6 –

+0

Nadal tego szukam. Nie chcę zaczynać używania "react-mixin". – Tom

Odpowiedz

19

Nie potrzeba używać EventEmitters wstawek.

Proste demo:

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

Pełne podpis addListener przyjmuje trzy argumenty:

EventEmitter.addListener(eventName, handler, handlerContext) 

w komponencie reagować, prawdopodobnie chcesz użyć tego argumentu kontekstowe, tak, że handler może być metoda klasy zamiast funkcji inline i nadal zachowuje this == component instance. Np .:

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: Mam to od patrzenia na zdecydowanie unmagical realizacji the infamous Subscribable mixin. Wyniki wyszukiwania Google to w zasadzie komora echa z demo Ramsaya opartego na jednym mixinie.

P.S. Jeśli chodzi o wystawienie tego emitera na inny komponent, prawdopodobnie zapewniłbym, że składnik będący właścicielem dostarcza funkcję do odbierania referencji emitera, a komponent, który tworzy emiter, warunkowo wykonałby ten rekwizyt z emiterem.

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

dziękuję! twoje "Proste demo" było dokładnie tym, czego potrzebowałem, aby go kliknąć. – iksnae

+0

Witaj Tomie, kiedy próbuję wywołać 'let test = new EventEmitter();' to wyrzuca 'undefined nie jest konstruktorem (oceniającym 'new _reactNative.EventEmitter()'), czy myślisz o tym? – Richard

+0

@Richard: Brak. Którą wersję native-reaktywnego używasz? Czy jesteś pewien, że zaimportowałeś poprawnie? Czy próbowałeś ponownie uruchomić program ładujący RN? Czy jest to błąd w czasie kompilacji lub wykonywania? – Tom

1

Udało mi się uzyskać obejście z react-mixin. Nie wiem, jak to jest prawidłowe, ale działa bez żadnych modyfikacji. Kluczem jest dodanie reactMixin(DetailView.prototype, Subscribable.Mixin); po definicji klasy.

pisali na przykład, że unosi się za EventEmitter i 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);