Home > Mobile >  Working with map fuction to get an specific react.js table output
Working with map fuction to get an specific react.js table output

Time:02-02

I am working with some data collected from a Json file. With a react fetch function I have created an object called "category_evolution". I am trying to use a map function to create a table with that object.

category_evolution =

[
    {
        "name": "01/02/2023",
        "data": [
            {
                "id": 30,
                "category": "Criptomoedas",
                "category_total_brl": "12000.00",
                "category_total_usd": "2400.00",
                "date": "01/02/2023"
            },
            {
                "id": 28,
                "category": "REITs",
                "category_total_brl": "16000.00",
                "category_total_usd": "3200.00",
                "date": "01/02/2023"
            },
            {
                "id": 26,
                "category": "Stocks",
                "category_total_brl": "20100.00",
                "category_total_usd": "4020.00",
                "date": "01/02/2023"
            }
        ]
    },
    {
        "name": "01/01/2023",
        "data": [
            {
                "id": 29,
                "category": "Criptomoedas",
                "category_total_brl": "10000.00",
                "category_total_usd": "2000.00",
                "date": "01/01/2023"
            },
            {
                "id": 27,
                "category": "REITs",
                "category_total_brl": "15000.00",
                "category_total_usd": "3000.00",
                "date": "01/01/2023"
            },
            {
                "id": 25,
                "category": "Stocks",
                "category_total_brl": "20000.00",
                "category_total_usd": "4000.00",
                "date": "01/01/2023"
            }
        ]
    }
]

Here is my table code:


<table className="table">
  <thead>
    <tr>
      <th scope="col">Categoria</th>
      {category_evolution.map(({ name }) => (
        <th scope="col" key={name}>{name}</th>
      ))}
    </tr>
  </thead>
  <tbody>
    {category_evolution.map(({ data }) =>
        data.map(({ id, category, category_total_brl }) => (
          <tr key={id}>
            <td>{category}</td>
            <td>{category_total_brl}</td>
          </tr>
        ))
      )}
  </tbody>
</table>

The output of this code is a table like that

Categoria            01/02/2023      01/01/2023

Criptomoedas         12000.00
REITs                16000.00
Stocks               20100.00

Criptomoedas         10000.00
REITs                15000.00
Stocks               20000.00

But I would like to achieve an output like this:

Categoria            01/02/2023      01/01/2023

Criptomoedas         12000.00        10000.00
REITs                16000.00        15000.00
Stocks               20100.00        20000.00

I appreciate any help you can provide.

CodePudding user response:

One way to do it is to combine all the data into a single array and then to map that array into an object where keys are the categories and the values are combined data for each "date":

const combinedData = category_evolution.reduce((acc, cur) => {
  return [...acc, ...cur.data];
}, []);

const categoryMap = combinedData.reduce((acc, cur) => {
  if(!acc[cur.category]) {
    acc[cur.category] = [cur];
    return acc;
  }
  acc[cur.category].push(cur);
  return acc;
}, {});

And then the JSX:

<table className="table">
  <thead>
    <tr>
      <th scope="col">Categoria</th>
      {category_evolution.map(({ name }) => (
        <th scope="col" key={name}>{name}</th>
      ))}
    </tr>
  </thead>
  <tbody>
    {Object.keys(categoryMap).map(category => {
      return (
        <tr key={category}>
          <th>{category}</th>
          <td>{categoryMap[category][0].category_total_brl}</td>
          <td>{categoryMap[category][1].category_total_brl}</td>
        </tr>
      )
    })}
  </tbody>
</table>

CodePudding user response:

Combined data provided from @o4ohel

const combinedData = category_evolution.reduce((acc, cur) => {
  return [...acc, ...cur.data];
}, []);

const categoryMap = combinedData.reduce((acc, cur) => {
  if(!acc[cur.category]) {
    acc[cur.category] = [cur];
    return acc;
  }
  acc[cur.category].push(cur);
  return acc;
}, {});

Here's an updated version of the code provided by @o4ohel that can be improved for readability and maintainability:


<table className="table">
    <thead>
        <tr>
        <th scope="col">Categoria</th>
        {category_evolution.map(({ name }) => (
            <th scope="col" key={name}>{name}</th>
        ))}
        </tr>
    </thead>
    <tbody>
    {Object.entries(categoryMap).map(([category, values]) => (
        <tr key={category}>
            <th>{category}</th>
            {values.map(({ id, category_total_brl }) => (
            <td key={id}>{category_total_brl}</td>
            ))}
        </tr>
        ))}
    </tbody>
</table>

A nested map is used to iterate over the values for each category, which allows for greater flexibility in case there are more or less values for each category in the future.

  • Related