7

Base component

import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { addToCart, removeFromCart, changeQuantity } from '../../actions/CartActions';

@connect(null, { addToCart, removeFromCart, changeQuantity })
class Product extends Component {
  constructor() {
    super();
    this.addToCart = this.addToCart.bind(this);
  }
  addToCart() {
    this.props.addToCart(this.props.product);
  }
  removeFromCart() {

    this.props.removeFromCart(this.props.product);
  }
  changeProductQuantity() {

    this.props.changeQuantity(this.props.product);
  }
  render() {
    return (
      <div className="product_box">
        <h3>{this.props.product.title}</h3>
        <Link to={`details/${this.props.product._id}`}>
          <img src={this.props.product.image_url} alt={this.props.product.title} />
        </Link>
        <p>{this.props.product.description}</p>
        <p className="product_price">{this.props.product.price} {this.props.product.currency}</p>
        <Link onClick={this.addToCart} className="addtocart" />
        <Link to={`details/${this.props.product._id}`} className="detail" />
      </div>
    );
  }
}

Product.propTypes = {
  product: PropTypes.shape({
    _id: PropTypes.string,
    title: PropTypes.string,
    description: PropTypes.string,
    image_url: PropTypes.string,
    price: PropTypes.string,
    currency: PropTypes.string,
  }),
  addToCart: PropTypes.func,
  removeFromCart: PropTypes.func,
  changeQuantity: PropTypes.func,
};

export default Product;

Child component

import React from 'react';
import Product from '../common/Product';

class InlineProduct extends Product {
  render() {
    const { product } = this.props;
    return (
      <tr>
        <td>
          <img src={product.image_url} alt={product.title} />
        </td>
        <td>{product.title}</td>
        <td className="align-center">
          <input className="quantity-input" type="text" value="1" onChange={this.changeProductQuantity} />
        </td>
        <td className="align-right">{product.price} {product.currency}</td>
        <td className="align-right">{product.price} {product.currency}</td>
        <td className="align-center">
          <a onChange={this.removeFromCart}>
            <img src="images/remove_x.gif" alt="remove" /><br />Remove
          </a>
        </td>
      </tr>
    );
  }
}

export default InlineProduct;

It's looks like second component can't inherit methods from first one. I can call parent's methods from child component. Any ideas? I think props validation is ok because it's static, but need some solution to make methods reachable form child component.

7
  • "I can call parent's methods from child component." That would be normal. Did you mean "can't"? Commented Oct 30, 2016 at 13:10
  • 1
    I'm having trouble finding the link, but I recall somewhere in the React documentation they say, basically, "In thousands of components at Facebook, we've never had a case where inheritance made sense over composition." Commented Oct 30, 2016 at 13:12
  • 4
    Found it: facebook.github.io/react/docs/composition-vs-inheritance.html Commented Oct 30, 2016 at 13:13
  • 1
    Thx, for your thoughts Commented Oct 30, 2016 at 13:23
  • 1
    So basically FB wants to throw years of accumulated CS knowledge out the window just because they haven't found a need for it. (Yes, I know they created React.) However, I would posit that most people aren't using React to build something like FB, and so they can't possibly say that you shouldn't use inheritance. Look at both approaches. Look at your requirements. Decide on the best approach. Commented Sep 4, 2020 at 19:00

1 Answer 1

9

If you want to use the parent's method inside children, you need to extend parent and call super in the constructor. super will run the constructor of the parent component. So, when you define or reference your method in the parent's constructor it can be accessible.

class A extends React.Component{
  constructor(props) {
    super(props)
    this.parentMethod = this.parentMethod.bind(this) //referencing the method in constructor
  }
  
  parentMethod(){
    console.log('Parent Method')
  }
  
  render(){
    return false
  }
}

class B extends A{
  constructor(){
    super() //call super to run parent's constructor
  }
  
  render(){
    this.parentMethod() //calling parent method
    return false
  }
}

ReactDOM.render(
  <div>
    <A/>
    <B/>
  </div>,
  document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Hope this helps!

Sign up to request clarification or add additional context in comments.

7 Comments

Just beware that React isn't designed to work well with this, they recommend not doing it, and several common practices with React components won't work with it.
@T.J.Crowder Thanks much for the heads up!
they recommend not doing it, but the reason mentioned is more like "React has a prowerful composition model, so use it", with no explanations about what things wouldn't work with inheritance. Any examples of common practices that wouldn't work with inheritance ? @T.J.Crowder
Late comment but, inheritance can lead to many coupling problems, which breaks the flexibility of an hierarchy of classes. The Strategy pattern, for example, is a composition-based solution for this. By looking for the motivation of use of strategy patterns, you will find the answer to why not use inheritance. It's not that it won't work, but it may lead to future problems and reduce the scalability of the application.
I struggle to believe that something as basic as inheritance is not recommended in react, how do you manage interfaces etc.... Seems broken by design every time I look at it
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.