Reputation: 130
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:
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
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
Reputation: 86220
Two options (or both!):
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