React - Can't get function to fire from child props

Viewed 57

I am trying to get this function to fire from on click call in a child component.

getTotalOfItems = () => {

 console.log('anything at all?')
 if (this.props.cart === undefined || this.props.cart.length == 0) {
    return 0
 } else {

  const items = this.props.cart
  var totalPrice = items.reduce(function (accumulator, item) {
    return accumulator + item.price;
  }, 0);

  this.setState({
    estimatedTotal: totalPrice
  });
  };
}

This on click is being fired from within a Cart component

<button onClick={() => {props.addToCart(item); props.getPrice.bind(this)} }>+</button>

The cart component is being added to the ItemDetails component here

export default class ItemDetails extends Component {
constructor(props) {
    super(props);
    this.state = {
        open: false
    };
}
render() {
    return(
        <div>
            <Button
            className="item-details-button"
            bsStyle="link"
            onClick={() => this.setState({open: !this.state.open})}
            >
            {this.state.open === false ? `See` : `Hide`} item details
            {this.state.open === false ? ` +` : ` -`}
            </Button>
            <Collapse in={this.state.open}>
                <Cart 
                getPrice={this.props.getPrice}
                />
            </Collapse>
        </div>
    )
 }
}

Finally the ItemDetails component is added into the app.js like so

 render() {
return (
  <div className="container">
    <Col md={9} className="items">
      <ProductListing products={this.props.initialitems} />
    </Col>
    <Col md={3} className="purchase-card">
      <SubTotal price={this.state.total.toFixed(2)} />
      <hr />
      <EstimatedTotal 
        price={this.state.estimatedTotal.toFixed(2)} />
      <ItemDetails 
        price={this.state.estimatedTotal.toFixed(2)}
        getPrice={ () => this.getTotalOfItems() }
      />
      <hr />
      <PromoCodeDiscount 
        giveDiscount={ () => this.giveDiscountHandler() }
        isDisabled={this.state.disablePromoButton}
      />
    </Col>
  </div>
);
};

If I remove the () = > before the this.getTotalOfItems() it fires the function on the onClick, however it causes an infinite loop of re-rendering out the app causing an error.

Is there anyway to fix this? I am a novice at React and this is one of my first projects using it. Any advice shall be appreciated.

Sorry if this isn't explained to well, I am happy to provide any additional information if required.

Thanks!

2 Answers

You have to trigger getPrice method, now all you do is binding this context. Instead of props.getPrice.bind(this) you should have: props.getPrice()

props.getPrice.bind(this) doesn't call the function it just binds 'this' to it.

You should use props.getPrice() instead, also you don't have to bind the context of a children to it.

Some additionnal tips/explanations :

You can rewrite all your functions calls like this one :

getPrice={ () => this.getTotalOfItems() }

to

getPrice={this.getTotalOfItems}

It will pass the function to the child instead of creating a function which trigger the function (same result, better performance)

But if you do this :

getPrice={this.getTotalOfItems()}

It'll trigger the function at each render(), causing an infinite loop if the function triggers a render() itself by calling this.setState()

Related