Reputation: 2990
How would I make a base class for my ReactJS components where I'd encapsulate some common behavior for all of the descendants.
Right now I have at least 3 classes that have a common method functionality
handleClick: function (e) {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
this.props.onClick(this.props.value);
},
which is copy/pasted. :(((
Coming from the C#, where I'd split everything into smallest possible pieces, this really bugs me.
Ideally I'd like to have such a method in base class
handleClick: function (e) {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
onClick(); // this method would be virtual in base class and overridden in children classes
},
Is it possible to achieve this in ReactJS? Or what would be another best approach for such functionality in ReactJS or JavaScript world?
Thx
Upvotes: 1
Views: 1906
Reputation: 1159
Have you considered using React Mixins.
This would allow you to define the function centrally and just mixin where you need it.
var HandleClickMixin = {
handleClick: function (e) {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
this.props.onClick(this.props.value);
}
};
Which can then be used:
var SomeReactComponent = React.createClass({
mixins: [HandleClickMixin],
render: function() {
return (
<button onClick={this.handleClick}>
Click Me.
</button>
);
}
});
You still need to provide the onClick and value props, but otherwise it's a one line addition.
Upvotes: 2
Reputation: 1426
In ReactJS world, it's generally preferred to use composition patterns over classical inheritance.
In your case, you could use the higher-order component pattern (very well explained in this post by Dan Abramov) like this:
// higher-order component creator:
function getClickHandlerComponent(OriginalComponent) {
const ClickHandlerComponent = React.createClass({
handleClick: function(e) {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
this.props.onClick(this.props.value);
},
render: function() {
return (
<OriginalComponent
{...this.props}
handleClick={this.handleClick}
/>
);
},
});
return ClickHandlerComponent; // higher-order component (HOC)
}
// Used like this:
const SomeButton = getClickHandlerComponent(React.createClass({
propTypes: {
// original props,
handleClick: React.PropTypes.func.isRequired, // added by the HOC
},
render: function() {
return (
<input
type="button"
value="Click me"
onClick={this.props.handleClick}
/>
);
},
}));
The functionality which is provided by the higher-order component (here, the "handleClick" handler) can be added to any component that needs it: the component simply receives it in its props.
Upvotes: 1
Reputation: 7209
Multiple ways
ES6 Classes: If you're using ES6 classes you can create a base class that extends Component
from react
and then extend your components from this base class
Context: If you take a look at react-router
you can get more implementation details but in short, context
is shared by all children and grandchildren so you could make your base component and then pass down methods to the children.
Upvotes: 0
Reputation: 13888
I would think of it more like a utility function that handles clicks, thats said, there are a number of ways to do this. Lets say we have a utility function(s) in a file called utils.js:
// utils.js
export function someUtilityFunction (a) {
return axios.all(players.map(function (username) {
return getUserInfo(username)
}))
.then(function (info) {
return info.map(function (user) {
return user.data
})
})
.catch(function (err) {console.warn('Error in func: ', err)})
};
Then in another file, lets say Main.js:
// Main.js
import { someUtilityFunction } from from '../utils/';
// someUtilityFunction is now available in this file
Note the export and import keywords.
Above I am using ES6 syntax, which needs to be transpiled down to ES5 for the browser (I use babel.js);
Take a look at these docs to see variations of this in both ES5 and ES6:
Upvotes: 0