0

I really think I'm going crazy here. So I made a shopping-type app, add to cart and etc.

I have extra comments on each Item which the user can enter any text they want to. The state is correct on "onChangeText" of the input, I checked it with the console. However, when I want to save it (after an edit of the cart), despite the console.log's making sense and that showing the correct state etc, the options changes successfully, but the comments does not. This is very weird as all the other cart array object do change, except the comment. Here is the code:

saveItemCart() {
    var index = this.state.cartItems.indexOf(x => x.date === this.state.dateAdded);
    let cartItemsArray = this.state.cartItems;
    temp = { 'catNumber': this.state.catNumber, 'itemNumber': this.state.itemNumber, 'quantity': this.state.itemQuantity, 'options': this.state.selectedOptions, 'date': this.state.dateAdded, 'comments': this.state.commentsText};
    cartItemsArray[index] = temp;

    this.setState({ cartItems: cartItemsArray }, () => {
        this.updateTotal();
        this.setState({ selectedOptions: [], checked: [] })
    })
}

State:

state = {
        ModalItemShown: false,
        ModalCartShown: false,
        ModalEditShown: false,

        isShowToast: false,
        isShowToastError: false,

        rest_id: this.props.route.params['restaurantid'],
        menuData: this.getMenu(),
        catNumber: 1,
        itemNumber: 1,
        dateAdded: null,
        commentsText: "",
        cartItems: [],

        checked: [],
        selectedOptions: [],

        total: 0,
        itemQuantity: 1,
    }

Input (inside the render):

    <View style={styles.modalOptions}>
          <Input placeholder="..." placeholderTextColor="gray" defaultValue={this.state.commentsText} onChangeText={text => this.setState({ commentsText: text }, () => {console.log(this.state.commentsText)})} />
     </View>
<Button shadowless style={styles.button1} color="warning" onPress={() => {
      let my = this;
      this.showToast(true);
      setTimeout(function () { my.showToast(false) }, 1000);
      this.saveItemCart();
      this.hideModalEdit(false);
      }}
 >Save</Button>

The problem is in the input of the EDIT cart modal(i.e. page). If the user puts the comment initially before adding it to his cart, then when he opens the edit modal it has the correct comment. If I change it in the edit and click save, and check again, it does not work.

updateTotal:

updateTotal() {
        var cartArrayLen = this.state.cartItems.length;
        var i;
        var j;
        var total = 0;
        var cart = this.state.cartItems;

        for (i = 0; i < cartArrayLen; i++) {
            var catNum = cart[i]["catNumber"];
            var itemNum = cart[i]["itemNumber"];
            var q = cart[i]["quantity"];


            var itemPrice = this.state.menuData[catNum - 1][catNum.toString()]["itemsarray"][itemNum]["price"];
            itemPrice = Number(itemPrice.replace(/[^0-9.-]+/g, ""));
            total = total + (itemPrice * q);

            var allItemOptions = this.state.menuData[catNum - 1][catNum.toString()]["itemsarray"][itemNum].options;

            var k;
            for (k = 0; k < cart[i].options.length; k++) {
                var title = cart[i].options[k]["title"];
                var index_onmenu = allItemOptions.findIndex(x => x.title === title);

                var option_price;
                if (Array.isArray(cart[i].options[k].indexes)) {
                    for (j = 0; j < cart[i].options[k].indexes.length; j++) {
                        var price_index = cart[i].options[k].indexes[j];

                        option_price = allItemOptions[index_onmenu].price[price_index]
                        total = total + Number(option_price) * q
                    }
                } else {
                    j = cart[i].options[k].indexes
                    option_price = allItemOptions[index_onmenu].price[j]
                    total = total + Number(option_price) * q
                }
            }

        };
        console.log("New Total: " + total);
        this.setState({ total: total }, () => {
            this.setState({ itemQuantity: 1 })
        })
    }
2
  • Please add updateTotal() code. Commented Apr 2, 2020 at 11:26
  • @Rajan I added it to the post :) Commented Apr 2, 2020 at 13:18

1 Answer 1

3

I don't see where you defined the temp variable, but assuming that it is defined somewhere, I think the problem is in how you are updating the cartItems array. Let me explain it by adding some comments in your code:

saveItemCart() {
    var index = this.state.cartItems.indexOf(x => x.date === this.state.dateAdded);
    let cartItemsArray = this.state.cartItems; // --> Here you are just copying the array reference from the state
    temp = { 'catNumber': this.state.catNumber, 'itemNumber': this.state.itemNumber, 'quantity': this.state.itemQuantity, 'options': this.state.selectedOptions, 'date': this.state.dateAdded, 'comments': this.state.commentsText};
    cartItemsArray[index] = temp;

    this.setState({ cartItems: cartItemsArray }, () => { // --> then you just updated the content of the array keeping the same reference
        this.updateTotal();
        this.setState({ selectedOptions: [], checked: [] })
    })
}

Try doing creating a new array, so the react shallow comparison algorithm can track the state change, like this:

this.setState({ cartItems: Array.from(cartItemsArray) }, /* your callback */);

or

this.setState({ cartItems: [...cartItemsArray]}, /* your callback */);

Hope it helps!

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

2 Comments

Hey thanks for this. But unfortunately, this does not work. Temp is declared, but the weird thing here is that both the temp variable is correct. The cartItemsArray is correct. It's at the setState that everything else updates correctly, except the comments. I tried both Array.from(cartItemsArray) and [...cartItemsArray], with the same result. :(
Problem solved, it was my index's fault. Thanks anyways

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.