6

Im trying to add up all of the calories in my array thats stored in the state.

  id: shortid.generate(),
  text: this.state.text,
  calorie: this.state.calorie

This is the data structure that being stored in the state array meals

Im currently running a forEach and using reducer to add up the values but its saying "reduce" is not a function I'm not sure what i'm doing wrong.

     class App extends Component {
  state = {
    meals: []
  };

  addMeal = meal => {
    this.setState({
      meals: [meal, ...this.state.meals]
    });
  };

  onDelete = id => {
    this.setState({
      meals: this.state.meals.filter(meal => meal.id !== id)
    });
  };
  render() {
    return (
      <div className="container">
        <div className="jumbotron">
          <h2>Calorie Counter</h2>
          <hr />
          <Form onsubmit={this.addMeal} />
          <table className="table table-striped">
            <thead>
              <tr>
                <th>Meal</th>
                <th>Calories</th>
                <th />
              </tr>
            </thead>
            <tbody>
              {this.state.meals.map(meal => (
                <Meal
                  key={meal.id}
                  meal={meal}
                  onDelete={() => this.onDelete(meal.id)}
                />
              ))}
              <tr>
                <td>Total:</td>
                <td>
                  {this.state.meals.forEach(meal =>
                    meal.reduce(function(y, x) {
                      return y + x;
                    }, 0)
                  )}
                </td>
                <td />
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

Im trying to display the total of calories inside of the meal in jsx

Saul
  • 311
  • 1
  • 2
  • 10
  • See also MDN: [`reduce`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) – p.s.w.g Jan 10 '19 at 03:45

3 Answers3

13

Reduce is an array function, not a meal object function. Try replacing the forEach with the reduce.

meals.reduce((totalCalories, meal) => totalCalories + meal.calorie, 0)

The first reduce assumes calories are numbers, the second is if strings

const meals = [
  { calorie: 10},
  { calorie: 15},
  { calorie: 20}
];

const calorieTotal = meals.reduce((totalCalories, meal) => totalCalories + meal.calorie, 0);

console.log(calorieTotal); // 45 calories

const mealsAsStrings = [
  { calorie: '11'},
  { calorie: '12'},
  { calorie: '13'}
];

const calorieStringTotal = mealsAsStrings.reduce((totalCalories, meal) => totalCalories + parseInt(meal.calorie, 10), 0);

console.log(calorieStringTotal); // 36 calories
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
2

You can't use reduce method on array elements as it's an array method. In the example above you are looping into the array and trying to call reduce with each element of array which is not right. You can do as follows -

this.state.meals.reduce((accumulator, currentValue) => accumulator + currentValue)

Hope that helps.

UPDATE - As you are trying to calculate calories from meal object array, we can do it as follows -

this.state.meals.reduce((accumulator, currentValue)=> accumulator + accumulator, currentValue.calorie,0);

Check the link for detail use of reduce method - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

Ashish
  • 419
  • 4
  • 7
  • this very much does help, but if i do this, the reducer receive an empty array, inside of meals contains the calories which in trying to add up – Saul Jan 10 '19 at 03:50
  • Is this the right meal array structure? var meals = [{id:1, cal:5}, {id:2, cal:7}, {id:3, cal:9}, , {id:4, cal:10}] – Ashish Jan 10 '19 at 04:05
  • yes its this [{id: "PxCoP4V6B", text: "cheetos", calorie: "100"}] ahh, it looks like it because it might be storing the value in string? – Saul Jan 10 '19 at 04:10
2

You can use yourArray.reduce like illustrated below: Given this array in ReactJs

const  App = () => {
  const course ='Half Stack application development'
  const empObj =[
    {
      employeename: 'Ndichu Kabata',
      salary: 10000
    },
    {
      employeename: 'George Githui',
      salary: 70000
    },
    {
      employeename: 'Super Omondi',
      salary: 40000
    }
] 
return (
    <div > 
     <Total  employees={empObj } />
    </div>
  );
}

and you are required to compute total salary. Do as follows:

const Total =(props) =>{
  const numbers = props.employees;
  const saloTotal = numbers.reduce((totalHolder,m) => totalHolder + m.salary,0);
  return(
        <>
           <p>Total Salary:  {saloTotal}</p>
        </>
  )}