Mjuice
Mjuice

Reputation: 1288

How to add a callback function to the .map method

I want my function to calculate the total cost of my shopping cart and then set the state of my component to those totals, but I need the calculation done first and then the state set after the calculations are complete. When I run the code below, the state never gets set.

renderCart: function() {

        var newSubtotal = 0;
        var newTotal = 0;

        this.props.cart.map((product)=>{

            newSubtotal += product.price;
            newTotal += product.price;
            newTotal *= 1.10;

            console.log("New Total ", newTotal);
            console.log("New Subtotal ", newSubtotal);

        }, () => {
            this.setState({
              subtotal: newSubtotal,
              total: newTotal
            });
        });


        return (
                    <div>
                        <ul>
                            <li>Subtotal: ${this.state.subtotal}</li>
                            <li>Discount: {this.state.discount}%</li>
                            <li>Tax: {this.state.tax}%</li>
                            <li>Total: ${this.state.total}</li>
                        </ul>
                      <button className="success button">Pay</button>
                    </div>

             ); 

    }

});

Upvotes: 0

Views: 65

Answers (3)

wintvelt
wintvelt

Reputation: 14101

In pseudo code, the structure of your component should look more like:

MyCartTotalComponent => {
  // no need for state: if your props contain cart, then every time cart changes
  // your component gets new props, calculates total, and renders
  render() {
    // calculate stuff and store in local cart variable
    var cart = {};
    cart.total = this.props.cart.reduce(
      function(prev,curr){
        return prev + curr.price;
      },0);
    // render stuff
    return (
      <div>
         ...
         <li>{cart.Total}</li>
         ...
      </div>
    );
  } 
}

Upvotes: 1

jackypan1989
jackypan1989

Reputation: 2866

two points:

  1. you should use .reduce function to calculate sum.
  2. you should not use this.setState in your render(), I suggest ComponentDidMount or InitialState

Upvotes: 1

trquoccuong
trquoccuong

Reputation: 2873

Map is synchronous . Why you need setState, use variable enough.

renderCart: function() {

        var newSubtotal = 0;
        var newTotal = 0;

        this.props.cart.map((product)=>{

            newSubtotal += product.price;
            newTotal += product.price;
            newTotal *= 1.10;

            console.log("New Total ", newTotal);
            console.log("New Subtotal ", newSubtotal);

        });


        return (
                    <div>
                        <ul>
                            <li>Subtotal: ${newSubtotal}</li>
                            <li>Discount: {this.state.discount}%</li>
                            <li>Tax: {this.state.tax}%</li>
                            <li>Total: ${newTotal}</li>
                        </ul>
                      <button className="success button">Pay</button>
                    </div>

             ); 

    }

});

Upvotes: 0

Related Questions