ReactJs - 在ES6中使用Mixins

时间:2015-06-17 02:32:39

标签: reactjs

关注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={?} />

关于如何最好地重构这个用于多种用途的任何想法?

谢谢...

2 个答案:

答案 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;
  };
}