Надействовать наследование компонентов ES6: работать, но не рекомендуется?

В настоящее время я наследую базовый компонент ES6 React следующим образом:

model.js(базовый компонент):

class ModelComponent extends React.Component {

    render() {
        // Re-used rendering function (in our case, using react-three ReactTHREE.Mesh)
        ...
    }

}

ModelComponent.propTypes = {
    // Re-used propTypes
    ...
};

export default ModelComponent;

Тогда у меня есть два расширяющихся компонента, которые выглядят в основном так:

import ModelComponent from './model';

class RobotRetroComponent extends ModelComponent {

    constructor(props) {

        super(props);

        this.displayName = 'Retro Robot';

        // Load model here and set geometry & material
        ...

    }

}

export default RobotRetroComponent;

(Полный исходный код здесь)

Это работает нормально. Обе модели появляются и работают так, как я ожидал.

Однако, я читал в нескольких местах, что наследование не является правильным подходом к React - вместо этого я должен использовать композицию. Но опять же, Mixins не поддерживаются в React v0.13?

Итак, это подход, который я принимаю выше ОК? Если нет, то какая проблема и как мне это сделать?

Ответы

Ответ 1

Команда Facebook рекомендует использовать "идиоматические концепции JavaScript" при написании кода React, и поскольку для классов ES6 нет поддержки mixin, нужно просто использовать композицию (поскольку вы просто используете идиоматические функции Javascript).

В этом случае вы можете иметь функцию composeModal, которая принимает компонент и возвращает его, завернутую в компонент контейнера более высокого порядка. Этот компонент более высокого порядка будет содержать любую логику, состояние и реквизит, которые вы хотите передать всем своим дочерним элементам.

export default function composeModal(Component){

   class Modal extends React.Component {

       constructor(props){
           super(props)
           this.state = {/* inital state */}
       }

       render() {
           // here you can pass down whatever you want 'inherited' by the child
           return <Component {...this.props} {..this.state}/>
       }

   }

   Modal.propTypes = {
      // Re-used propTypes
      ...
   };

   return Modal
}

Затем вы можете использовать композиционную функцию следующим образом:

import composeModal from './composeModal';

class RobotRetroComponent extends React.Component {

    constructor(props) {
        super(props);
        this.displayName = 'Retro Robot';
        // Load model here and set geometry & material
        ...
    }

    render(){
        return /* Your JSX here */
    }
}

export default composeModal(RobotRetroComponent);