Is using both Inheritance and Composition a good practice in React Class Components?

821 views Asked by At

I will best explain what I am trying to say with an example: I want to create a hoverable component which can be reused. If I use only extension the code will look like this:

Inheritance:

class HoverableComponent extends React.Component {
    
    constructor(props){
        super(props);
        this.state = {hover: false}
    }

    protected abstract customRender();

    render(){
        return <div
        onMouseOver={() => this.setState({hover: true})}
        onMouseOut={() => this.setState({hover: false})}
        >
        {this.customRender()}
        </div>
    }

}

class MyClass extends HoverableComponent {
    
    customRender(){
        return ... // do stuff with this.state.hover
    }
}

The downside of this is that I have to use the customRender function in order to render the component.

Composition:

class HoverableComponent extends React.Component {

    render(){
        return <div
        onMouseOver={() => this.props.onHoverChange(true))}
        onMouseOut={() => this.props.onHoverChange(false))}
        >
        {this.props.children}
        </div>
    }

}

class MyClass extends React.Component {

    constructor(props){
        super(props);
        this.state = {hover: false}
    }

    handleHoverChange = (hover) => this.setState({hover: hover});

    render(){
        return <HoverableComponent
               onHoverChange={this.handleHoverChange}
               >
               ... JSX ....
               </HoverableComponent
    }

}

The down side of this approach is that I have to create a state variable in the parent component, but I get to render in a reactfuly way

So I was thinking if I can use both ways to get what I want or it will end up in a really messy code.

Both

class HoverableComponent extends React.Component {
    
    constructor(props){
        super(props);
        this.state = {hover: false}
    }

    render(){
        return <div
        onMouseOver={() => this.setState({hover: true})}
        onMouseOut={() => this.setState({hover: false})}
        >
        {this.props.children}
        </div>
    }

}


class MyClass extends HoverableComponent {

    render(){
        return <HoverableComponent>
                // do stuff with this.state.hover
               </HoverableComponent>
    }

}


For this case which of these 3 methods is considered to be a best practice ? Is there any other way I should use ? I want to scale this up to also have for example, DraggableComponent, ClickableComponent, etc.

1

There are 1 answers

0
yasaman rezaeeshirsavar On

React recommend using composition instead of inheritance as much as possible and inheritance should be used in very specific cases only.

https://www.tutorialspoint.com/composition-vs-inheritance-in-react-js#:~:text=Composition%20and%20inheritance%20are%20the,in%20very%20specific%20cases%20only.

For preventing duplicate multiple times why you don't implement reusable methods as a custom hook. You can define all the methods you need once and use them wherever you want.

const [handleHoverChange]= useHoverableComponent();