1

I know this may seem like a repeat and I have read the similar questions and answers. However I am still having an issue getting my parent component and its state to sync up with its child component. It is just one step behind, even in the console.

Parent Component App.js

changeItemQuantity = (id, newQuantity) => {
        this.setState(prevState => ({
            cartData: {
                ...prevState.cartData,
                items: this.state.cartData.items.map(item => {
                    if (String(item.productData.productId) === String(id)) {
                        item.productQuantity = newQuantity
                    }
                    return item
                })
            }
        }))

        // console.log(id, newQuantity);
        // console.log(this.state.cartData)
    }

Child Component Cart.js

import React, { Component } from 'react';

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

        this.state = {
            newQuantity: 1
        }
    }

    handleQuantityChange = (e) => {
        this.setState({
            newQuantity: e.target.value
        })

        this.props.changeItemQuantity(e.target.id, this.state.newQuantity);
    }

    render() {
        return (
            <div className="cart-list">
                {this.props.cartData.items.map(item => {
                    return (
                        <div className="cart-item" key={item.productData.productId}>
                            <div className={`cart-item-image ${item.productData.productImage}`}></div>

                            <div className="cart-item-data">
                                <div className="cart-item-name">{item.productData.productName}</div>
                                <div className="cart-item-s-q">( {item.productSize} ) x <input type="text" id={item.productData.productId} onChange={this.handleQuantityChange} className="cart-field change-q" placeholder={item.productQuantity}/></div>
                                <div className="cart-item-total">Total : ${(parseInt(item.productData.productPrice) * parseInt(item.productQuantity)).toFixed(2)}</div>
                            </div>
                        </div>
                    )
                })}
            </div>
        )
    }
}

export default Cart;

Basically what I am trying to accomplish is being able to be inside of the shopping cart page of my ecom site and adjust the quantity of each item (which is held inside of the parents state). I have that figured out, but when I adjust, the state inside the console and on the screen is not up to date. I have tried using a callback function like so

handleQuantityChange = (e) => {
        this.setState({
            newQuantity: e.target.value
        }, this.props.changeItemQuantity(e.target.id, this.state.newQuantity);)

    }

But that did nothing for me. I also tried using a callback inside of the Parent component like so...

 changeItemQuantity = (id, newQuantity) => {
        this.setState(prevState => ({
            cartData: {
                ...prevState.cartData,
                items: this.state.cartData.items.map(item => {
                    if (String(item.productData.productId) === String(id)) {
                        item.productQuantity = newQuantity
                    }
                    return item
                })
            }
        }), console.log(this.state.cartData))

    }

But again, nothing. What do you guys suppose I could do? Thanks in advance!

  • `item.productQuantity = newQuantity` this is [mutating the old state which is an anti-pattern](https://stackoverflow.com/q/37755997/1218980), and chances that it's the source of the problem. – Emile Bergeron May 28 '20 at 00:40
  • Does this answer your question? [Whats the best way to update an object in an array in ReactJS?](https://stackoverflow.com/questions/28121272/whats-the-best-way-to-update-an-object-in-an-array-in-reactjs) – Emile Bergeron May 28 '20 at 00:41
  • Also, inside `handleQuantityChange `, when you call `this.props.changeItemQuantity(e.target.id, this.state.newQuantity);`, it's still the old state since [`this.setState` doesn't immediately update the state.](https://stackoverflow.com/q/30782948/1218980) – Emile Bergeron May 28 '20 at 00:44
  • In your other example where `this.setState({ /**/ }, this.props.changeItemQuantity(/**/);)`, [you're not passing a callback to `this.setState`](https://stackoverflow.com/q/42038590/1218980), you're calling the function immediately. – Emile Bergeron May 28 '20 at 00:45
  • Same thing with the last `console.log`. – Emile Bergeron May 28 '20 at 00:49

0 Answers0