0

I'm writing a Product component in react.js, and I'd like to increase the inCartCount value of actual product when the item is clicked.

import React, { PropTypes } from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Product.css';

var NumberFormat = require('react-number-format');
class Product extends React.Component {

    addToCart(product) {
        console.log(product.inCartCount);
        product.inCartCount++;
    }

    render() {

        const product = this.props.data;

        product.inCartCount = product.inCartCount || 0;

        return (
            <div onClick={this.addToCart.bind(this, product)}>
                <h3>{product.name}</h3>
                <NumberFormat value={product.price} displayType={'text'} thousandSeparator={true} suffix={' Ft'}/>
                <span>{product.inCartCount}</span>
            </div>
        );
    }
}

export default withStyles(s)(Product);

in console.log the value is increasing, but it is not rendered to DOM, I always see 0 as inCartCount value in the browser.

3 Answers 3

1

Problem is you are reinitialising the product in render every time, possible solutions:

  1. Update the parent component with new count, pass a function from parent to child.

In Parent Component:

<Product
    updateProduct={this.updateProduct.bind(this)}
    data={this.state.data}    
/>

updateProduct(value){
    this.setState({data:value});
}

In Child Component:

addToCart(product) {
    console.log(product.inCartCount);
    product.inCartCount++;
    this.props.updateProduct(product);
}

2. Store the product in state on child component like this:

import React, { PropTypes } from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Product.css';

var NumberFormat = require('react-number-format');

class Product extends React.Component {
     constructor(props) {
       super(props);
       this.state = {
         product: props.data
       };
     }  

    addToCart() {
       let product = this.state.product;
       product.inCartCount = product.inCartCount ? product.inCartCount+1 : 1;
       this.setState({product});
    } 

    render() {
       return (
          <div onClick={this.addToCart.bind(this)}>
              <h3>{this.state.product.name}</h3>
              <NumberFormat value={this.state.product.price} displayType={'text'} thousandSeparator={true} suffix={' Ft'}/>
              <span>{this.state.product.inCartCount}</span>
          </div>
       );
    }
}

export default withStyles(s)(Product);
Sign up to request clarification or add additional context in comments.

2 Comments

updating count in child like this product.inCartCount++; is not correct this should be moved to parent product should be immutable and not update-able
i dont know his product structure, i just told him all the possible ways of solving the issue he is facing. if he just want the data in child component then no need to pass it to parent again.
1

You can't use code like you do it. To increment the counter you should use this.state.counter and use this variable into you component. Because every time when your this.state changed, your component automatically re-rendering and take new this.state. If you just change the value manually how you did this - components isn't re-rendering and you never see the changed value at the page. But don't forget to initalizing the this.state = {counter: 0}; at first in the method getInitialState() Like this:

  getInitialState() {
    return { counter: 0 };
  }

and use it into render method or into any methods like this.state.counter

1 Comment

he is using es6, getInitialState() will not work, he have to use constructor.
1

You fetch the product each time from the props which is immutable and will never be updated, you have 2 options here:

  1. Update parent with the new count and set its state to update product and that will re-render child with new product props and have a new count
  2. Initialize state with the props from parent and then you are controlling the state for product and in this case you will need to set the state to new product after updating the count to re-render

Comments

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.