3

I have an existing React component created by React.createClass method. I want to reuse that React component by using class extend feature in ES6 (for method overriding purpose) but the result is unexpected. Example:

//an existing React component created via React.createClass
var ab = React.createClass({
    say(){
        console.log('ab class')
    },
    render(){
        return null;
    }
});

class c1 extends ab {
    say(){
        console.log('c1 class')
    };
}

o = new c1();
console.log(o.say()); //The expected console output is "c1 class" 
                      //but its showing "ab class"
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
Hung Tran
  • 233
  • 1
  • 3
  • 9
  • 1
    afaik theres no way to extend new off old syntax. However its really easy to convert your old component to ES6 the syntax is very similar – undefined Mar 10 '16 at 06:54
  • Sorry, I don't get your point. I'm using babel javascript compilier to convert ES6 syntax so it should not be syntax problem. My problem is the method say() implemented in both class ab and c1 is not override as expected – Hung Tran Mar 10 '16 at 07:03
  • React classes != ES6 classes - they're completely different things, the former is specific to React, the latter is just a standard JavaScript construct. As @LukeMcGregor said, you can't extend an old style component with an ES6 one, at least not with the ES6 `extends` syntax. Your only option is probably to update `ab` to an ES6 class if you want to extend it like that. – Joe Clay Mar 10 '16 at 14:57
  • @JoeClay, could you please give me an example code to update "ab" to an ES6 class? – Hung Tran Mar 10 '16 at 15:28
  • @HungTran - Posted as an answer! – Joe Clay Mar 10 '16 at 15:30

1 Answers1

4

React classes are not the same as ES6 classes - the former is specific to React, the latter is just a standard JavaScript construct. As LukeMcGregor said, you can't extend an old style component with an ES6 one, at least not with the ES6 extends syntax. Your only option is probably to update ab to an ES6 class if you want to extend it like that:

import React from "react";

class ab extends React.Component {
    say() {
        console.log('ab class')
    }

    render() {
        return null;
    }
}

class c1 extends ab {
    say() {
        console.log('c1 class')
    }
}

There are a few caveats to consider when using ES6 classes rather than React classes, namely the lack of the autobinding feature the latter provides. More info, and ways to work around it can be found here: http://www.ian-thomas.net/autobinding-react-and-es6-classes/.

EDIT: Okay, seeing as you can't edit the original class, here's another idea (honestly, it's probably a better idea than extending an existing component). A common concept in React is that of 'Composition' - this is where you create a component that wraps around an existing one. A component created in this way is often referred to as a 'higher order component'; in your case, it might look something like this:

import React from "react";

var ab = React.createClass({
    say() {
        console.log('ab class')
    },

    render() {
        return (<div>I am the AB class</div>);
    }
});

class c1 extends React.Component {
    say() {
        console.log('c1 class')
    };

    render() {
        return (<ab />);
    }
}

This may seem like it doesn't approximate inheritance, but you can actually do a lot with it - if you want to pass data back and forth between your existing component and the new composed one, you can just use the props on the ab component (seeing as it's a 3rd party component in your case, I imagine it has a pretty well defined API). If you need to access the methods from the base class, you can use refs, as described in this answer.

Composition is a really powerful pattern - one of the main ways I use it in my apps is by creating entirely stateless components for the UI, and then creating 'container' components that wrap around and connect them up to the data they need. This creates a really nice separation between the UI and the logic (Dan Abramov wrote about the concept here - he's about 10000x smarter than I am and I'd be terrible at React without some of the stuff he's posted).

Community
  • 1
  • 1
Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • 1
    Don't forget `class ab extends React.Component` – Mulan Mar 10 '16 at 15:43
  • Thanks for your answer, actually I'm facing with the issue that "ab" component is from a3rd package, so I could not modify the "ab". Is there any way to implement an ES6 wrapper class (eg: abWrapper) that has all function for "ab" component so that I just extend from that ES6 wrapper class? – Hung Tran Mar 10 '16 at 17:21
  • @HungTran - I edited my answer with a quick rundown of composing components - this is probably a better approach than the one I originally posted, and will work with both ES6 and React classes :) – Joe Clay Mar 10 '16 at 18:08
  • This is how I would do it if i were unable to edit the original :) – undefined Mar 10 '16 at 19:39