关注Egghead.io的视频 - “ES 6课程中的反应组件”,以下内容有效:
'use strict';
import React from 'react';
import Button from './components/form/button';
import Label from './components/form/label';
// after refactoring
//import ReactMixin from './super-classes/react-mixin';
// ToDo:反应堆
let reactMixin = InnerComponent => class extends React.Component {
constructor() {
super()
this.state = {count: 0}
//binding custom methods
this.increment = this.increment.bind(this);
}
increment() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<InnerComponent update={this.increment} {...this.state} {...this.props} />
)
}
}
let ButtonMixed = reactMixin(Button); // using local variable
let LabelMixed = reactMixin(Label); // using local variable
class App extends React.Component {
render(){
return(<section>
// WOULD LIKE TO DO
// <ReactMixin component={?Button?} />
// <ReactMixin component={?Label?} />
<LabelMixed txt="I am a mixed label calling a form component" />
<ButtonMixed txt="I am a mixed button, me too! " />
</section>);
}
}
App.propTypes = {txt: React.PropTypes.any};
module.exports = App;
问题:
我正在尝试将ReactMixins重构为一个单独的组件,将其导入, 然后在我的渲染中使用它,如下所示:
<ReactMixins component={?} />
关于如何最好地重构这个用于多种用途的任何想法?
谢谢...
答案 0 :(得分:6)
更新:在使用ES6 React组件完成更多工作之后,我更赞成合成方法,但我会在此留下我的答案给后人。< / p>
Mixins正在出路,而不是赞成组合或继承。
如果我理解你的情况,最简单的方法就是创建一个&#34; base&#34;您继承的组件。类似的东西:
export default class BaseButton extends React.Component {
constructor(){
super();
//Set default state... if you want to
}
componentWillMount() {
console.log("I will run anytime someone extends baseButton");
}
//etc
}
你所有的Button逻辑都是,那么你可以像这样扩展它
然后:
export default class MyButton extends BaseButton {
//I will already have the things that BaseButton has
}
现在,您已通过super()
或this.whatever()
获得了所需的一切。
如果你赞成合成方式,我推荐这是一个很好的读物:
https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
答案 1 :(得分:1)
如果您使用装饰器,我的ES6 mixins解决方案。
/**
* This is the ES6 mixin helper
*
* mixins {Array} Array of mixin objects
* mixin:
* optional name: {String} mixin's name
* optional lifecycleMethods: {Object} lifecycle methods
* optional instances: {Object} instance methods
* optional statics: {Object} statics methods
* component {Object} Abstract component
*
* return component {Object} mixed component
*/
export default function ES6Mixin (mixins) {
return function (component) {
const warn = function (type, method, mixinName) {
console.warn(
new component(),
`already has \`${method}\` ${type} method, it's overwritten by \`${mixinName}\` mixin`
);
};
mixins.forEach((mixin) => {
const { name, statics, instances, lifecycleMethods } = mixin;
const _componentWillMount = component.prototype.componentWillMount;
if (statics instanceof Object) {
Object.keys(statics).forEach((method) => {
if (statics[method] instanceof Object) {
component[method] = Object.assign({}, statics[method], component[method]);
} else {
if (this[method]) {
warn('statics', method, name || 'anonym');
}
this[method] = statics[method];
}
});
}
if (instances instanceof Object) {
component.prototype.componentWillMount = function () {
Object.keys(instances).forEach((method) => {
if (this[method]) {
warn('instance', method, name || 'anonym');
}
this[method] = instances[method].bind(this);
});
if (_componentWillMount) {
_componentWillMount.apply(this, arguments);
}
};
}
if (lifecycleMethods instanceof Object) {
Object.keys(lifecycleMethods).forEach((method) => {
let _lifecycleMethod = component.prototype[method];
component.prototype[method] = function () {
lifecycleMethods[method].apply(this, arguments);
if (_lifecycleMethod) {
_lifecycleMethod.apply(this, arguments);
}
};
});
}
});
return component;
};
}