How to display sum of each column in react

Viewed 1054

I want to display sum of pharmacy and sum of client number for each region in the table.

In each array object I have pharmacy and client data. I want to group them as per the region and Region should be the column header.

I grouped the json object based on the region.

I not able to sum the data in the table.

I am getting first value only in the each column not the sum of table.

allstates.json:

 [
          {
            "id": "AL",
            "val": "01",
            "bgcolor": "green",
            "pharmacy": 10,
            "client": 20,
            "region": "Northeast"
          },
          {
            "id": "AR",
            "val": "05",
            "bgcolor": "green",
            "pharmacy": 10,
            "client": 12,
            "region": "Northeast"
          },
          {
            "id": "DE",
            "val": "10",
            "bgcolor": "red",
            "pharmacy": 10,
            "client": 20,
            "region": "MidAtlantic"
          }, 
           {
            "id": "FL",
            "val": "12",
            "bgcolor": "red",
            "pharmacy": 10,
            "client": 20,
            "region": "MidAtlantic"
          },
          {
            "id": "GU",
            "val": "66",
            "bgcolor": "red",
            "pharmacy": 30,
            "client": 20,
            "region": "Southease"
          },
          {
            "id": "HI",
            "val": "15",
            "bgcolor": "red",
            "pharmacy": 10,
            "client": 20,
            "region": "Southease"
          },
          {
            "id": "ID",
            "val": "16",
            "bgcolor": "red",
            "pharmacy": 10,
            "client": 20,
            "region": "Southease"
          },
          
]

summary.js:

import React from "react";
import allStates from "./data/allstates.json";
import groupBy from 'lodash/groupBy';
import './App.css'

const Summary = () => {

  let grouppedArray = groupBy(allStates, 'region')
  return (
    <table class="table">
      <thead>
        <tr>
          {Object.keys(grouppedArray).map(key => {
            return (
              <th>{key}</th>
            )
          })}
        </tr>
      </thead>

      <tbody>
        <tr>
          {Object.values(grouppedArray).map(values => {
            console.log(values, "values")
            var pharmacyTotal = 0;
            var clientTotal = 0;
            for (let i = 0; i < values.length; i++) {
              pharmacyTotal += values[i].pharmacy;
              console.log(values[i].pharmacy, "test")
              pharmacyTotal = values[i].pharmacy + i;
              clientTotal += values[i].client;
              return (
                <td>
                  <p>Pharmacy:{pharmacyTotal}</p>
                  <p>Client: {clientTotal}</p>
                </td>
              )

            }

          })}

        </tr>
      </tbody>
    </table>
  );

};

export default Summary;
4 Answers

you can use these function to group your data and then map through it to fill your table:

const groupData = (x)=>{
   let temp = [];
   let grouped = [];
   x.map(e=>{
     if(temp.includes(e.region)){
       let idx = grouped.findIndex(item=>item.region===e.region);
       grouped[idx].pharmacy += e.pharmacy;
       grouped[idx].client += e.client;
       return;
   } else {
      temp.push(e.region);
      grouped.push(e);
   }
   });
   return grouped;
}

First transform the data and sum up the costs per region

const result = [{
    "id": "AL",
    "val": "01",
    "bgcolor": "green",
    "pharmacy": 10,
    "client": 20,
    "region": "Northeast"
  },
  {
    "id": "AR",
    "val": "05",
    "bgcolor": "green",
    "pharmacy": 10,
    "client": 12,
    "region": "Northeast"
  },
  {
    "id": "DE",
    "val": "10",
    "bgcolor": "red",
    "pharmacy": 10,
    "client": 20,
    "region": "MidAtlantic"
  },
  {
    "id": "FL",
    "val": "12",
    "bgcolor": "red",
    "pharmacy": 10,
    "client": 20,
    "region": "MidAtlantic"
  },
  {
    "id": "GU",
    "val": "66",
    "bgcolor": "red",
    "pharmacy": 30,
    "client": 20,
    "region": "Southease"
  },
  {
    "id": "HI",
    "val": "15",
    "bgcolor": "red",
    "pharmacy": 10,
    "client": 20,
    "region": "Southease"
  },
  {
    "id": "ID",
    "val": "16",
    "bgcolor": "red",
    "pharmacy": 10,
    "client": 20,
    "region": "Southease"
  },

].reduce((acc, current) => {
  const {
    pharmacy,
    client,
    region
  } = current;
  const currentRegionState = acc[region] ?? {
    pharmacyTotal: 0,
    clientTotal: 0
  };
  acc[region] = {
    clientTotal: currentRegionState.clientTotal + client,
    pharmacyTotal: currentRegionState.pharmacyTotal + pharmacy,
  };
  return acc;
}, {});


console.log(result);

And then you can iterate over that new data with Object.values

You're returning in a for loop which will cause the loop to stop execution and exit the function. In your case, it's returning the first iteration of the loop and moving on. You also have a bug where you're resetting pharmacyTotal in the loop.

Instead, return outside of the loop like so:

{Object.values(grouppedArray).map((values) => {
  var pharmacyTotal = 0;
  var clientTotal = 0;

  for (let i = 0; i < values.length; i++) {
    pharmacyTotal += values[i].pharmacy;
    clientTotal += values[i].client;
  }

  return (
    <td>
      <p>Pharmacy: {pharmacyTotal}</p>
      <p>Client: {clientTotal}</p>
    </td>
  );
})}

It looks like you're using lodash which provides a method called sumBy which will simplify this code.

{Object.entries(grouppedArray).map(([key, values]) => (
  <td key={key}>
    <p>Pharmacy: {sumBy(values, "pharmacy")}</p>
    <p>Client: {sumBy(values, "client")}</p>
  </td>
))}

If you prefer to write the sumBy function yourself, have a look at reduce.

function sumBy(values, key) {
  return values.reduce((total, value) => total += value[key], 0)
}

Here's the code in action: https://codesandbox.io/s/youthful-joliot-qy6qq

You can loop through the result from following to print accordingly in table.

const grouppedArray = _(allStates).groupBy('region')
const result = grouppedArray.map((state) => ({
    region: state[0].region,
    client: _.sumBy(state, 'client'),
    pharamcy: _.sumBy(state, 'pharmacy')
  }))
Related