2015-02-05 2 views
7

Ho un modulo React che funziona correttamente in ES5. Lo sto convertendo in ES6 e usando 6to5 per la conversione. Tutto traspone bene, ma ottengo un errore di runtime quando sto cercando di impostare il mio props. Quando rilascio uno debugger e guardo allo this, vedo che lo this è lo EventEmitter e non la classe. Qui è il mio codice:Come risolvere `questo` nella conversione del modulo React nella classe ES6

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

    .... 
}; 

Il posto che sto avendo il problema è nella mia funzione changeView. Quando è transpiled giù sembra che questo:

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

Anche in questo caso, all'interno di quella funzione, this è il mio EventEmitter. Qual è il modo di risolvere questo problema?

risposta

16

this.setProps è deprecato, utilizzare lo stato per questo. Ti fornirà questo avviso in 0.13:

Attenzione: setProps (...) è deprecato nelle classi JavaScript React semplici.

Anche i metodi di classe es6 non sono associati automaticamente, quindi è necessario eseguirne il binding manualmente. È possibile utilizzare .bind(this) o utilizzare le funzioni freccia. Per gli emettitori esterni, tuttavia, è necessario mantenere un riferimento.

Si può solo sbarazzarsi di _onChange:

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

o vincolare nel costruttore:

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

Non dimenticate di separare l'evento in componentWillUnmount:

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

L'aggiunta di listener di eventi dovrebbe essere eseguita in componentDidMount, non in componentWillMount. Il costruttore sostituisce componentWillMount nelle classi es6.

Questo codice è molto male ... si sta ignorando l'puntelli reagiscono set:

this.props = { 
    view: 'weeks' 
} 

Basta sostituire tutte le occorrenze di 'oggetti di scena' con 'stato' nel codice, e tutto sarà buono. Probabilmente vorrai anche lo stato iniziale del negozio.

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

Inoltre, createClass non sta andando via in qualunque momento presto, quindi sentitevi liberi di continuare ad usarlo. È spesso più semplice I negozi dovrebbero generalmente essere gestiti da mixin, cosa banale con createClass, ma più difficile da fare proprio nelle classi es6. Ho una piccola biblioteca per mixins with react and es6 classes.

+0

Puoi mostrarmi un blog o da qualche parte che spiega come i negozi dovrebbero essere gestiti da mixin? – jhamm

+0

La maggior parte delle implementazioni di flusso ne fornisce una. Il mixin gestisce lo stato iniziale dal negozio, ascolta il negozio e fa this.setState quando c'è un cambiamento. Pulisce anche il listener quando il componente è smontato. Ecco un esempio di [fluxxor store mixin] (http://fluxxor.com/documentation/store-watch-mixin.html) – FakeRainBrigand

+0

@FakeRainBrigand cosa succede se uso anche il flusso e imposta un valore predefinito come questo? '_handleStoreChange = (stato: Object = {}) => {..}' Ricevo un errore di sintassi con babel 'Assegnazione a rvalue' – tsm