2015-02-05 6 views
7

Ich habe ein React-Modul, das in ES5 funktioniert. Ich wandle es in ES6 um und verwende 6to5 für die Umwandlung. Alles läuft gut, aber ich bekomme einen Laufzeitfehler, wenn ich versuche, meine props einzustellen. Wenn ich eine debugger fallen lasse und this betrachte, sehe ich, dass this die EventEmitter ist und nicht die Klasse. Hier ist mein Code:So lösen Sie `this 'beim Umwandeln von React-Modul in ES6-Klasse

var React = require('react'); 

import CalendarStore from './../stores/calendar.store.js'; 

function getAppointments() { 
    return {appts: CalendarStore.getAppts()} 
} 

export default class extends React.Component{ 
    constructor(props) { 
    super(props); 
    this.props = { 
     view: 'weeks' 
    } 
    } 

    changeView(child, view) { 
    this.setProps({view: view}); 
    } 

    componentWillMount() { 
    CalendarStore.addChangeListener(this._onChange); 
    } 

    _onChange() { 
    this.setProps(getAppointments()); 
    } 

    .... 
}; 

Der Ort, wo ich das Problem habe in meiner changeView Funktion. Wenn es transpiled nach unten sieht es so aus:

_onChange: { 
     value: function _onChange() { 
     this.setProps(getAppointments()); 
     }, 
     writable: true, 
     configurable: true 
    } 

Auch innerhalb dieser Funktion ist this meine EventEmitter. Wie kann man das beheben?

Antwort

16

this.setProps ist veraltet, verwenden Sie den Status dafür. Es gibt Ihnen diese Warnung in 0.13:

Warnung: SetProps (...) wird in normalen JavaScript React Klassen veraltet.

Auch es6 Klassenmethoden sind nicht autobound, so dass Sie es manuell binden müssen. Sie können entweder .bind(this) verwenden oder Pfeilfunktionen verwenden. Für externe Emitter müssen Sie jedoch eine Referenz behalten.

Sie können nur von _onChange loszuwerden:

this._calendarListener = e => this.setState({things: e}); 
CalendarStore.addChangeListener(this._calendarListener); 

Oder binden im Konstruktor:

constructor(props){ 
    ... 
    this._onClick = this._onClick.bind(this); 
} 

Vergessen Sie nicht, das Ereignis in componentWillUnmount zu entbinden:

componentWillUnmount(){ 
    CalendarStore.removeChangeListener(this._onClick); 
    // or 
    CalendarStore.removeChangeListener(this._calendarListener); 
} 

Das Hinzufügen von Ereignis-Listenern sollte in componentDidMount und nicht in componentWillMount erfolgen. Der Konstruktor ersetzt ComponentWillMount in es6-Klassen.

Dieser Code ist sehr schlecht ... Sie überschreiben die Requisiten Sätze reagieren:

this.props = { 
    view: 'weeks' 
} 

alle Vorkommen von ‚Requisiten‘ ersetzen mit ‚Staat‘ in Ihrem Code, und alles wird gut sein. Wahrscheinlich möchten Sie auch den Ausgangszustand des Geschäfts.

this.state = { 
    view: 'weeks', 
    things: CalendarStore.getAppts() 
} 

Auch ist createClass nicht weg in absehbarer Zeit, so fühlen sich frei, ihn weiterverwenden. Es ist oft einfacher. Stores sollten generell mit Mixins behandelt werden, was bei createClass trivial ist, in es6-Klassen jedoch schwieriger. Ich habe eine kleine Bibliothek für mixins with react and es6 classes.

+0

Können Sie mir einen Blog zeigen oder irgendwo, wo erklärt wird, wie Geschäfte von Mixins gehandhabt werden sollen? – jhamm

+0

Die meisten Flussmittelimplementierungen bieten eins. Das Mixin verarbeitet den Anfangszustand aus dem Speicher, hört den Speicher ab und führt bei Änderungen einen this.setState aus. Außerdem wird der Listener bereinigt, wenn die Komponente deaktiviert wird. Hier ist ein Beispiel für einen [fluxxor store mixin] (http://fluxxor.com/documentation/store-watch-mixin).html) – FakeRainBrigand

+0

@FakeRainBrigand Was ist, wenn ich auch Flow verwende und einen Standardwert wie diesen einstelle? '_handleStoreChange = (state: Object = {}) => {..}' Ich bekomme einen Syntaxfehler mit babel 'Assigning to rvalue' – tsm