Search code examples
javascriptreactjsmappingstateshopping-cart

How to maintain previous changed state in REACT JS as when new item is updated, previous is set to default?


I have a shopping Cart in react (Not using Redux) which has Quantity input field infront of each item. Qty is 1 by default for all. TotalPrice for each item is infornt of it(unitPrice*1). Now if user updates Qty value, TotalPrice needs to be updated(unitPrice*Qty). My code is doing it but issue is when i update one item Qty, it updates Price, great, but when I update another item Qty, previously updated Price gets reset to default (back to UnitPrice).

I searched it alot but no use. Most People use redux but I dont want to use it. So please help me if u see a solution to it as I want to maintain all the updated prices.

export default class Cart extends Component
{
  constructor(props) {
      super(props);

      this.state = {
        data:[],
        customer: '',
        redirectToReferrer: false,
        cart: [],
        cartItems: [],
        
        qty: '',
        clicked: ''      };
 this.onChangeQty = this.onChangeQty.bind(this);
}

componentDidMount() {
 
    const retrieved = localStorage.getItem("cartItem");
    const arr = JSON.parse(retrieved);
    axios.post('http://localhost/Auth/api/customers/show_cart.php', arr,
     {
    headers: {'Accept': 'application/json, text/plain, */*',
              'Content-Type': 'application/json'}
    } )
    .then(response => {
    this.setState({
             cartItems :response.data.records
           });
      })
     .catch(error => {
     if (error) {
       console.log("Error");  }
       });

}


onChangeQty(sid,e)
{
this.setState({
  clicked: sid,
  qty: e.target.value })

}

  render()
  {
    return (
<div id="profileDiv">

<Col md="12" lg="12" sm="12" xs="12">
<h1> <b> Your Shopping Cart </b>  </h1>

<Table>
<thead>
    <tr className="text-center">

        <th> Item# </th>
        <th> Image </th>
        <th> ID</th>
        <th> Name</th>
        <th> Unit Price </th>
        <th> Quantity </th>
        <th> Total Price </th>

    </tr>
</thead>

<tbody>
{this.state.cartItems.map( (item, i) =>

  <tr>

    <td className="text-center">
      <h4 key={i}> {i}</h4>
    </td>

    <td className="text-center">
    <Image src={"data:image/png[jpg];base64," +  item.Image}
     id="cartImage" alt="abc" />
    </td>

    <td className="text-center">
      <h4>{item.SparePartID}</h4>
    </td>

    <td className="text-center">
      <h4> {item.Name}</h4>
    </td>

    <td className="text-center">
      <h4 >{item.Price} </h4>
    </td>

    <td className="text-center">
      <h4 key={item.SparePartID}>
      <input className="text-center"
       type="number"
      min="1"
      onChange={(e) => this.onChangeQty(item.SparePartID, e)}
      />
      </h4>
    </td>

    <td className="text-center">
      <h4 key={item.SparePartID}>
      {
         this.state.clicked == item.SparePartID ?
         (item.Price*this.state.qty) : item.Price     
      }
      </h4>
    </td>

  </tr>

)}  </tbody>
</Table>
</Col>
</div>  ); }
}


Solution

  • What you need to do is, when you get your cart items, to go through each item and to add a quantity for each of them. And add a total in state for the total of all products.

    constructor(props) {
          super(props);
    
          this.state = {
            data:[],
            customer: '',
            redirectToReferrer: false,
            cart: [],
            cartItems: [],
            totalPrice: 0
            clicked: ''      };
     this.onChangeQty = this.onChangeQty.bind(this);
    }
    
    componentDidMount() {
    
        const retrieved = localStorage.getItem("cartItem");
        const arr = JSON.parse(retrieved);
        axios.post('http://localhost/Auth/api/customers/show_cart.php', arr,
         {
        headers: {'Accept': 'application/json, text/plain, */*',
                  'Content-Type': 'application/json'}
        } )
        .then(response => {
        let myItems = [];
        response.forEach(item => {
          myItems.push({id: item.id, name: item.name, qty: 1, price: item.price, total: item.price});
        })
        this.setState({
                 cartItems :myItems
               });
          })
         .catch(error => {
         if (error) {
           console.log("Error");  }
           });
    
    }
    

    OnChange method should find the selected product and update its quantity, and the totalPrice:

    onChangeQty(sid,e)
    {
      const items = this.state.cartItems;
      const item = items.find(item => item.id === sid);
      const index = items.indexOf(item);
      item.qty = e.target.value;
      item.total = item.qty * item.price;
      items[index] = index;
    
      let totalPrice = 0;
      items.forEach(item => {
          totalPrice += item.qty * item.price;
      });
    
      this.setState({
        cartItems: items,
        totalPrice
      });
    
    }
    

    and in html you can show the total price as

    {this.state.totalPrice}
    

    and if you want total of each item you can simply check it by

    this.state.cartItems.forEach(item => {
        console.log(item.total);
    })