javascriptreactjsmethodscomponentshigh-order-component

Displaying the Sum of values in React JSX


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


Solution

  • 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