1

I'm learning React.js (and I'm a beginner at JavaScript) and having some difficulty getting my addToCart function working properly. I've managed to get all my products to display but adding to cart on any of them only adds the first item, and once that item is out of stock then all the items go out of stock.

I'm sure I'm missing something obvious but would really appreciate some more experienced eyes on my code please.

Github repo for this app

Below are my FluxProduct.react.js product components:

var React = require('react');
var FluxCartActions = require('../actions/FluxCartActions');

var FluxProduct = React.createClass({

  addToCart: function(event){
    var id = this.props.selected.id;
    var update = {
      name: this.props.product.name,
      category: this.props.selected.category,
      price: this.props.selected.price
    }
    FluxCartActions.addToCart(id, update);
    FluxCartActions.updateCartVisible(true);
  },

  render: function() {
    var self = this;
    var products = this.props.product;
    var stockAvailable = (this.props.selected.id in this.props.cartitems) ? this.props.selected.stock - this.props.cartitems[this.props.selected.id].quantity : this.props.selected.stock;
    return (
      <ul>
      {Object.keys(products).map(function(product){
      return (
        <li key={product}>
          <div className="flux-product">
            <img src={'img/' + products[product].image}/>
            <div className="flux-product-detail">
              <h1 className="name">{products[product].name}</h1>
              <p className="category">{products[product].category}</p>
              <p className="description">{products[product].description}</p>
              <p className="price">Price: ${products[product].price}</p>
              <button type="button" onClick={self.addToCart} disabled={stockAvailable  > 0 ? '' : 'disabled'}>
                {stockAvailable > 0 ? 'Add To Cart' : 'Sold Out'}
              </button>
            </div>
          </div>
        </li>
        )
        })}
      </ul>
    );
  },

});

module.exports = FluxProduct;

Relevant FluxCartApp.react.js components:

render: function(){
    return (
      <div className="flux-cart-app">
        <FluxCart products={this.state.cartItems} count={this.state.cartCount} total={this.state.cartTotal} visible={this.state.cartVisible} />
        <FluxProduct product={this.state.product} cartitems={this.state.cartItems} selected={this.state.selectedProduct} />
      </div>
    );
  },

Relevant cart actions:

selectProduct: function(index){
    AppDispatcher.handleAction({
      actionType: FluxCartConstants.SELECT_PRODUCT,
      data: index
    })
  },

  addToCart: function(id, update){
    AppDispatcher.handleAction({
      actionType: FluxCartConstants.CART_ADD,
      id: id,
      update: update
    })
  },

Sorry but I'm not sure what further relevant code needs to be pasted, if anyone has any advice I'd be grateful.

sanjsanj
  • 1,003
  • 9
  • 20

1 Answers1

1

You're accessing the products variable from inside your map function, when instead you should be using the product parameter that is passed to it. Additionally, why map on the keys of products, just us the products as an array:

<ul>
{products.map(function(product){
return (
  <li key={product}>
    <div className="flux-product">
      <img src={'img/' + product.image}/>
      <div className="flux-product-detail">
        <h1 className="name">{product.name}</h1>
        <p className="category">{product.category}</p>
        <p className="description">{product.description}</p>
        <p className="price">Price: ${product.price}</p>
        <button type="button" onClick={self.addToCart.bind(null, product.id)} disabled={stockAvailable  > 0 ? '' : 'disabled'}>
          {stockAvailable > 0 ? 'Add To Cart' : 'Sold Out'}
        </button>
      </div>
    </div>
  </li>
  )
  })}
</ul>

Notice that I've used bind to pass the product ID through to addToCart as well, and this lets us use it like this, with the bound ID passed as the first argument:

addToCart: function(id, event){
    var update = {
      name: this.props.product.name,
      category: this.props.selected.category,
      price: this.props.selected.price
    }
    FluxCartActions.addToCart(id, update);
    FluxCartActions.updateCartVisible(true);
}

You may also be interested in the answer "JavaScript variable binding and loop" which may have been a contributing factor in your problem and often catches out JavaScript newcomers.

Community
  • 1
  • 1
Colin Ramsay
  • 16,086
  • 9
  • 52
  • 57
  • The only thing I had to change in your code was to add .id in `
  • ` on line 4, and then `product` worked great, thanks for that! But my problem is still there, adding any item to cart just adds the first item. How would I use the product ID passed through to `addToCart` please?
  • – sanjsanj Jun 16 '15 at 18:00