feners
feners

Reputation: 675

How to loop through an array of objects and get specific key values in React?

I want to use either forEach or map to loop through an array that has multiple objects in it. These objects have a key price and a value for it. I'm was trying to use forEach but I can't get it to work. This is my component:

import React, { Component } from 'react';
import {addCart} from './Shop'; 
import { connect } from 'react-redux';

export class Cart extends Component {
    constructor(props) {
        super(props);
        this.state = {items: this.props.cart,cart: [],total: 0};
    }

    ...

    countTotal() {
        this.state.cart.forEach((item, index) => {
            console.log(this.state.items);
            this.state.total = this.state.total + this.state.items.price;
            console.log(this.state.total);
        })
    }

    ...

    render() {
        return(
            <div className= "Webcart" id="Webcart">
            </div>
        );
    }
}

...

In countTotal, console.log(this.state.items) outputs various objects that each look like

item:"Hoodie"
price:25
size:"large"

How can I loop through each object and get the price value so I can add it up in my function?

Upvotes: 0

Views: 3199

Answers (2)

user2065736
user2065736

Reputation:

To answer how to loop through an array, you can use a simple for loop in javascript as you would in a language like C;

let total = 0;
for(let i = 0; i < items.length; i++) {
    total += item[i].price
}

React following a functional approach, we prefer map and reduce as it makes your code more declarative. Hence,

const total = items.reduce((acc, item) => {
  return acc + item.price;
}, 0)

Your code would look like this then,

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';


export class Cart extends Component {
  constructor(props) {
    super(props);
    this.state = {items: props.cart,cart: [],total: 0};
  }


  countTotal() {
    return this.state.items.reduce((acc, item) => {
      return acc + item.price;
    }, 0)
  }

  render() {
    return(
      <div className= "Webcart" id="Webcart">
        { this.countTotal() }
      </div>
    );
  }
}

class App extends Component {
  render() {
    return (
      <Cart cart={
              [
                {
                  item:"Hoodie",
                  price:25,
                  size:"large"
                },
                {
                  item:"Gloves",
                  price: 12,
                  size:"large"
                },
                {
                  item:"boots",
                  price:30,
                  size:"large"
                },
              ]
            } />
    );
  }
}

export default App;

Note There is not setState used. total is derived data. Derived data must not reside in state.

Yet if for some reason you still need it, countTotal would look like this,

countTotal() {
   this.setState(state => {
     return {
        total: state.items.reduce((acc, item) => {
          return acc + item.price;
        }, 0)
     };
   });
}

Upvotes: 0

Rob M.
Rob M.

Reputation: 36511

You should not assign directly to state, you should use setState instead. forEach is fine, but I would recommend you skip forEach and map and use reduce, pulling only the price key out of the object:

countTotal() {
   this.setState({
      total: this.state.cart.reduce((total, { price }) => total + price, 0)
   });
}

Upvotes: 3

Related Questions