Iliyan Peychev
Iliyan Peychev

Reputation: 130

React JS inheritance

I have question regarding React and especially the way it is supposed to share common functionality. From what I read, the preferred way is using mixings, correct?

I have the following problem: I have a toolbar and buttons. Toolbar is one React class and each Button is a separate class. All buttons share same common functionality:

  1. They all create something on init.
  2. They all execute common action on click.

I extracted this common functionality in single mixin. It has two functions for these two similar things. I'm passing what is specific to the functions in the mixin from each button. The problem is that I have now another button which does no fit in that picture. On click, it should do something completely different. I can't reuse the second functionality (handling the click) from the mixin.

Of course, I thought to create a separate function handleClick only in this button, which will override the one in the mixin. However, it seems this is not possible - React forbids overriding functions, not part of the lifecycle.

Would you give me some advices what is the preferred way to resolve this situation? Maybe to create two mixins and just to not use the second one for the button which does not fit in the common picture?

Thanks,

Upvotes: 2

Views: 3505

Answers (2)

WiredPrairie
WiredPrairie

Reputation: 59763

Another option rather than mixins is to create a base/abstract button that is used by the various specialty types of buttons (through a compositional pattern). Here's a simple demo.

What I've done is create an AbstractButton that has basic button clicking behavior. You could put things that are common to all of your buttons there for example.

With that, I've created a second class called RealButton1. It uses AbstractButton and handles the a click event (onClick). Then, I've created a second specialization of a button called SecondRealButton. Both can behave different and still be reused as necessary.

While mixins work today, there isn't an obvious path forward for them yet given the recent announcements of starting to support EcmaScript 6 syntax. Also, from that same blog post, you'll note how they specifically mention that there isn't any mixin support for ES6 classes.

In this case, I wouldn't recommend using a mixin as you (presumably) own the UI components and aren't trying to provide an extension model for another pluggable system (like might be necessary for example with a router or store/flux/dispatcher type system).

var AbstractButton = React.createClass({
    propTypes: {
        onClick: React.PropTypes.func
    },
    handleClick: function(e) {
        if (this.props.onClick) {            
            this.props.onClick.call(this, e);
        }
    },
    render: function() {
       return <button onClick={this.handleClick}>
                 {this.props.caption}
              </button>;
    }        
});

var RealButton1 = React.createClass({
    propTypes: {
        caption: React.PropTypes.string.isRequired
    },

    render: function() {
        return <AbstractButton 
                  onClick={ this.clicked }  
                  caption={ this.props.caption } />;        
    },

    clicked: function(e) {
        console.log('clicked ' + this.props.caption);    
    }

});

var SecondRealButton = React.createClass({
    propTypes: {
        caption: React.PropTypes.string.isRequired
    },

    render: function() {
        return <AbstractButton onClick={ this.clicked }
                caption={ this.props.caption } />;        
    },

    clicked: function(e) {
        console.log('second type clicked ' + this.props.caption);    
    }    
});

var SampleApp = React.createClass({    
    render: function() {        
        return (<div>
                <RealButton1 caption="button 1" />
                <RealButton1 caption="button 2" />
                <SecondRealButton caption="other type button #1" />
            </div>        
        );    
    }
});

React.render(<SampleApp />, document.body);

Upvotes: 5

Brigand
Brigand

Reputation: 86220

Two options (or both!):

  • create two mixins
  • use a name other than handleClick

In mixins you usually want less generic names. handleClick is very vague, and you can't instantly see the implementation, or even know it's coming from a certain mixin. If you give it a more qualified name like handleToolSelect, it'll be clearer and you can just pretend it doesn't exist in your components that don't need it.

Upvotes: 1

Related Questions