Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React ES6 component inheritance: working, but not recommended?

Tags:

I'm currently inheriting an ES6 React base component in the following way:

model.js (base component):

class ModelComponent extends React.Component {

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

}

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

export default ModelComponent;

Then I have two extending components that both look basically like this:

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;

(Full source code here)

This appears to work fine. Both models are showing up and working as I would expect.

However, I have read in multiple places that inheritance is not the correct approach with React - instead I should be using composition. But then again, Mixins are not supported in React v0.13?

So, is the approach I'm taking above OK? If not, what's the problem, and how should I do this instead?

like image 808
poshaughnessy Avatar asked May 15 '15 12:05

poshaughnessy


People also ask

Should you use inheritance in React?

React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components.

What base class do React components inherit from?

Inheritance allows the app to do the coupling between the parent-child component and reuse properties such as state values and function in its child components. React does not use inheritance except in the initial component class, which extends from the react package.

Which API is must for every Reactjs component?

The renderComponent is a must API for every React. js component.

Which choice will not cause a React component to Rerender?

React does not render two sibling elements unless they are wrapped in a fragment.


1 Answers

The Facebook team recommends 'using idiomatic JavaScript concepts' when writing React code, and since there is no mixin support for ES6 classes, one should just use composition (since you are just making use of idiomatic Javascript functions).

In this case, you can have a composeModal function that takes a component and returns it wrapped in a higher-order, container component. This higher-order component will contain whatever logic, state, and props you want passed down to all of its children.

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
}

Then you can use the composition function like so:

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);
like image 199
Jonathan Huang Avatar answered Sep 16 '22 18:09

Jonathan Huang