2015-11-24 16 views
10

Voglio usare un po 'di astrazione nella creazione dei miei componenti React. Per esempio:Abstraction in React.js

class AbstractButton extends React.Component { 
    render() { 
    return (
     <button 
     onClick={this.props.onClick} 
     className={this.definitions.className}> 
     {this.props.text} 
     </button> 
    } 
} 
class PrimaryButton extends AbstractButton { 
    constructor(options) { 
    super(options); 
    this.definitions = { 
     className: 'btn btn-primary' 
    }; 
    } 
} 
class SuccessButton extends AbstractButton { 
    constructor(options) { 
    super(options); 
    this.definitions = { 
     className: 'btn btn-success' 
    }; 
    } 
} 

io non voglio passare questi definitions via props perché so che queste definitions --in questo caso il class --sia non cambiano mai.

È un anti-pattern in React? O è OK?

La mia domanda si riferisce a this altjs issue: questo tipo di astrazione non è compatibile con @connectToStores.

+2

React tende a concentrarsi su Composition, piuttosto che sull'ereditarietà, ma il tuo codice non mi sembra malvagio. – christopher

+3

Sì, è generalmente considerato un anti-pattern. Ecco un interessante articolo a riguardo: https://medium.com/@dan_abramov/how-to-use-classes-and-sleep-at-night-9af8de78ccb4 –

risposta

10

In generale, non c'è ragione per non utilizzare la composizione qui invece di eredità profonda:

class Button extends React.Component { 
    render() { 
    return (<button 
      onClick={this.props.onClick} 
      className={this.props.className} 
      > 
      {this.props.text} 
      </button>); 
    } 
    static propTypes = { 
     className: React.PropTypes.string.isRequired, 
     onClick: React.PropTypes.func 
    } 
} 

class PrimaryButton extends React.Component { 
    render() { 
    return <Button {...this.props} className="btn btn-primary" />; 
    } 
} 

Questo è solo funzionale come quello che si propone, ma è molto più semplice e più facile da ragionare su. Rende molto chiaro quali informazioni il tuo Button abbia effettivamente bisogno di fare il suo lavoro.

Una volta che fate questo salto, è possibile eliminare le classi del tutto e utilizzare componenti senza stato:

const Button = (props) => (<button 
      onClick={props.onClick} 
      className={props.className} 
      > 
      {props.text} 
      </button>); 
Button.propTypes = { 
     className: React.PropTypes.string.isRequired, 
     onClick: React.PropTypes.func 
}; 

const PrimaryButton = (props) => 
    <Button {...props} className="btn btn-primary" />; 

const SuccessButton = (props) => 
    <Button {...props} className="btn btn-success" />; 

Questo permetterà Reagire ad applicare più ottimizzazioni in quanto i componenti non hanno bisogno di alcun supporto evento del ciclo di vita speciale o la gestione dello stato . È anche più facile ragionare, visto che ora lavori solo con funzioni pure.

Per inciso, se stai cercando di creare alcuni componenti React che avvolgono Bootstrap, forse dovresti dare un'occhiata a React-Bootstrap.