0

How to push an item to an item array within state.The Addcartbutton component adds a new item to state.items.But each time when i add new item the state.items is not updated. `

    import React from 'react';
    import Addtocartbutton from '../component/addcart';
    import Cart from '../component/cartlist';
    export default class Product extends React.Component {

    constructor() {
        super();
        this.state = {
            items: [],
            total: 0,
            currency: 'INR'
        }
        this.addtocart = this.addtocart.bind(this);
    }

    addtocart(data) {
        console.log(data);
        this.setState({
            items:[this.state.items,data]
        })
        console.log(this.state.items);
    }

    render() {
        var list = this.props.dataname;
        return (
            <div className="card hoverable">
                <div className="card-image">
                    <img src={list.image} alt={list.name} className='shop-img' />
                </div>
                <div className="card-content">
                    <span className="card-title blue-text text-darken-2">{list.price}&nbsp;{list.currency}</span>
                    <p>{list.name}</p>
                </div>
                <Addtocartbutton  onClick={this.addtocart.bind(this,list)} />
            </div>
        )
        return(
        <Cart datalist={this.props.items}/>
       )
      };


     }

Tried this.state.items.push() but dosen't seems to work at all.Also how to pass item array as a props to Cart component from Product component.

import React from 'react';

export default class Cart extends React.Component {

    render() {
        let p = this.props.datalist;
        console.log(p);
        return (
            <ul className="collection">
                <li className="collection-item avatar">
                    <img src="#" alt="" className="circle" />
                    <span className="title">dfdfd</span>
                    <a href="#!" className="secondary-content"><i className="material-icons">grade</i></a>
                </li>
            </ul>
        )
    }
}

4 Answers 4

1

Try this it may help

addtocart(data) {
    console.log(data);
    let items = this.state.items.slice();
    items.push(data);
    this.setState({
        items:items
    }, ()=> {
      console.log(this.state.items);
    })
    
}

Steps of method

1- first i create a new variable from this.state.items.slice() which will return new array instance.

2- simply push the data into the array and set the state of items

3- Arrays are reference type in javascript, to update the state you have to pass a new array thus I am passing the new items array (let items = this.state.items.slice();)

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

Comments

0

you can't mutate directly as this.state.push but you need to extend the object

 addtocart(data) {
        console.log(data);
        this.setState(prevState => ({
            items:[...prevState.items, data]
        }))
    }

Example code:

Edit 1qyzx71ovq

16 Comments

"doesn't work" isn't helpful. What specifically is the issue when you try it? The exact issue, error messages, etc.
For Milos' answer, you'll need to have the proper plugin for transpiling the spread/rest operator
prevState = this.state.items; this.setState(prevState => ({ items:[prevState,data] })) is this correct ??
only one item is present within the items array.Still the array is not getting updated after each click.
No because you're setting the old state EQUAL to the new one. You need to create a copy of old state values you use if they are arrays/objects. Try something like this.setState({items:this.state.items.slice().concat(data)})
|
0

I believe the issue is with the onClick on the addtocartbutton component. Just have the onClick function as <Addtocartbutton onClick={this.addtocart(list)} /> and follow the code given by Milos. (I wish I could comment on the first answer, but I do not have enough reputation).

Also, the addtocart method is already bound in the constructor, so there is no need to bind it again.

Comments

0

As addtocart is already binded in the constructor, no need to bind it again. so update your code as below.

<Addtocartbutton onClick={this.addtocart(list)} />

and update your addtocart method as shown below. (I have used closure concept here)

addtocart(data) {
  return function() {
    this.setState(prevState => ({
        items:[...prevState.items, data]
    }))
  }.bind(this)  
}

or use the below code which uses the arrow functions.

addtocart = data => () => {
    this.setState(prevState => ({
      items: [...prevState.items, data]
    }));
  };

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.