2014-12-01 15 views
7

Nota: Questo post è stato pubblicato al momento in cui React NON supporta ES6 (v12).Ereditarietà React ed ES6

Ho un classe ES6:

class BaseClass { 
    getInitialState(){ 
     return {message: 'Hello!'}; 
    } 

    render() { 
     return (
      <div> 
       <div>{this.state.message}</div> 
      </div> 
     ) 
    } 
} 

Che posso esportare in ES6 usando questa espressione (fonte: react ES6 browserify)

export default React.createClass(BaseClass.prototype) 

Questo funziona bene. Ora vorrei usare ES6 ereditarietà per estendere il mio BaseClass classe:

class ExtendedClass extends BaseClass{ 
    getInitialState(){ 
     return {message: "Hello! I'm an extension"}; 
    } 
} 

Ma quando chiamo React.createClass sulla classe ExtendedClass, ho ottenuto la seguente eccezione:

Invariant Violation: ReactCompositeComponentInterface: You are attempting to define `constructor` on your component more than once. This conflict may be due to a mixin. 

So Reagire 0,13 si suppone essere più amichevoli di ES6 ma esiste un modo per gestirli?

EDIT:

sto usando Traceur per compilare le mie classi ES6. L'uscita per ExtendedClass assomiglia:

function ExtendedClass() { 
    "use strict"; 
    if (BaseClass !== null) { 
    BaseClass.apply(this, arguments); 
    } 
} 
for (BaseClass____Key in BaseClass) { 
    if (BaseClass.hasOwnProperty(BaseClass____Key)) { 
     ExtendedClass[BaseClass____Key] = BaseClass[BaseClass____Key]; 
    } 
    } 
    ____SuperProtoOfBaseClass = BaseClass === null ? null : BaseClass.prototype; 
    ExtendedClass.prototype = Object.create(____SuperProtoOfBaseClass); 
    ExtendedClass.prototype.constructor = ExtendedClass; 
    ExtendedClass.__superConstructor__ = BaseClass; 
    ExtendedClass.prototype.getInitialState = function() { 
    "use strict"; 
    return {message: "Hello! I'm an extension"}; 
    }; 
    React.createClass(ExtendedClass.prototype); 
+0

getInitialState non deve essere usato con il codice di ES6. Invece, imposta il tuo stato iniziale nel costruttore, 'costruttore (oggetti di scena) {super (oggetti di scena); this.state = {message: 'Hello!'}} ' – widged

+0

Questo post è stato pubblicato al momento in cui React NON supporta ES6 (v12). Non è più rilevante. Ovviamente con React v13 tutto funziona correttamente e non è necessario utilizzare la soluzione menzionata. – JBE

risposta

1

Ecco la soluzione che ho trovato:

All'interno React.js biblioteca, ho aggiornato il ReactCompositeComponentInterface per aggiungere un criterio personalizzato per constructor (Per quanto ne so non c'è modo di personalizzare questo 'interfaccia' correttamente):

var ReactCompositeComponentInterface = { 

/** 
* An array of Mixin objects to include when defining your component. 
* 
* @type {array} 
* @optional 
*/ 
mixins: SpecPolicy.DEFINE_MANY, 

/** 
* Custom policy for 'constructor' 
*/ 
constructor: SpecPolicy.DEFINE_MANY, 

    ... 

} 

Poi nel ExtendedClass, è necessario ridefinire ogni metodo, anche se non li personalizza:

class ExtendedClass extends BaseClass{ 
    getInitialState(){ 
     return {message: "Hello! I'm an extension"}; 
    } 
    /** required */ 
    render(){ 
     return super.render(); 
    } 
} 

Non sono felice con questa soluzione sporca, ma farà il lavoro in attesa di una versione 0.13 che si spera risolverà tali problemi.

6

C'è un bel post su come scrivere ReactJS in ES6.

http://ilikekillnerds.com/2015/02/developing-react-js-components-using-es6/

In ogni caso quando si utilizza ES6 non si usa React.createClass. basta creare la classe che estende React.Component

Anche in ES6 non hai getInitialState non defaultProps. è sostituito a favore usando this.state all'interno del costruttore.

Dai un'occhiata a questo esempio. Supponiamo che tu abbia il componente Card e il pannello di benvenuto che estende il componente Card.

Il codice è il seguente: Componente

Carta:

import React , { Component } from 'react' 
class Card extends Component { 
    constructor(props){ 
    super(props); 
    } 

    render() { 
    return (
     <div className="card"> 
      <div className="card__content"> 
      <label>{this.props.content}</label> 
      </div> 
     </div> 
    ) 
    } 

    initPanel(el,content){ 
    React.render(<Card content={content} />, el); 
    } 
} 

export default Card; 

Benvenuto Componente del pannello:

import React from 'react'; 
import Card from 'components/card.component'; 

class WelcomePanel extends Card { 
    constructor(props){ 
    super(props); 
    this.state = { 
     content: "Welcome Panel", 
     index: 0 
    } 
    } 

    componentClicked(){ 
    this.setState({content: "Component Clicked", index: this.state.index + 1}) 
    } 

    render() { 
    return (
     <div className="welcome-panel" onClick={this.componentClicked.bind(this)}> 
     <Card content={`${this.state.content} ${this.state.index > 0 ? this.state.index : ''} ${this.state.index > 0 ? 'times' : ''} `} /> 
     </div> 
    ) 
    } 

    initPanel(el,content){ 
    React.render(<WelcomePanel />, el); 
    } 
} 

export default { Class: WelcomePanel }