Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React and ES6 inheritance

Note: This post has been posted at the time React was NOT supporting ES6 (v12).

I have an ES6 class :

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

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

That I can export in ES6 using this expression (source : react ES6 browserify)

export default React.createClass(BaseClass.prototype)

This works fine. Now I would like to use ES6 inheritance to extend my BaseClass class :

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

But when I call React.createClass on the ExtendedClass class, I got the following exception :

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

I know React 0.13 is supposed to be more ES6 friendly but is there any ways to handle that ?

EDIT:

I'm using Traceur to compile my ES6 classes. The output for ExtendedClass looks like :

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);
like image 900
JBE Avatar asked Dec 01 '14 17:12

JBE


People also ask

Does React support inheritance?

Inheritance allows the app to do the coupling between the parent-child component and reuse properties such as state values and function in its child components. React does not use inheritance except in the initial component class, which extends from the react package.

Does React support ES6?

React uses ES6, and you should be familiar with some of the new features like: Classes. Arrow Functions. Variables (let, const, var)

Is React Createclass deprecated?

Use plain JavaScript classes instead. If you're not yet ready to migrate, create-react-class is available on npm as a drop-in replacement.


1 Answers

There is a great post about writing ReactJS in ES6.

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

Anyway when using ES6 you don't use React.createClass. you just create class that extends React.Component

Also in ES6 you don't have getInitialState not defaultProps. it's replaced in favor using this.state inside constructor.

Check out this example. Let's say you have Card component and Welcome Panel that extends Card component.

The code is as following:

Card Component:

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;

Welcome Panel Component:

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 }
like image 196
Vladimir Novick Avatar answered Oct 04 '22 02:10

Vladimir Novick