4

I'm trying to display some data received through API to table in React Js, data is received as object so I can't map trough it. What would be the best practice in this situation? For now the data is hardcoded, but it needs to be dynamic.

My code in CodeSandbox

export default function App() {

  const data ={
    
    "people" :[
      {
        "name":"John",
        "last_name":"Doe",
        "age":"25",
        "Occupation":"driver",
      },
      {
        "name":"Jack",
        "last_name":"Brown",
        "age":"24",
        "Occupation":"it"
      },
      {
        "name":"Oliver",
        "last_name":"Black",

        "age":"30",
        "Occupation":"cto"
      },
    ],

    "format":{"last_name":"Last Name"}
  }
  
  return (
    <div className="App">
     <table>
       <tbody>
         <tr>
           <td>Name</td>
           <td>John</td>
           <td>Jack</td>
           <td>Oliver</td>
           
         </tr>
         <tr>
           <td>Last Name</td>
           <td>Doe</td>
           <td>Brown</td>
           <td>Black</td>
           
         </tr>
         <tr>
           <td>Age</td>
           <td>25</td>
           <td>24</td>
           <td>30</td>
           
         </tr>
         <tr>
           <td>Occupation</td>
           <td>driver</td>
           <td>it</td>
           <td>ceo</td>
         </tr>

         
       </tbody>
     </table>
    </div>
  );
}


needs to be displayed as

Name         John     Jack      Oliver
Last Name    Doe      Brown     Black
Age          25       24        30
Occupation   driver   it        ceo

I can't figure out how to display the data dynamically ( and also add data from format part. I would appreciate any suggestion and help, thank you.

3 Answers 3

5

My approach is somewhat unorthodox, but may still be of interest to you. I would actually render your data like so first:

Name    Last Name   Age Occupation
John    Doe         25  driver
Jack    Brown       24  it
Oliver  Black       30  cto

And then simply use CSS to transpose it, which will give it the look you want:

Name         John     Jack      Oliver
Last Name    Doe      Brown     Black
Age          25       24        30
Occupation   driver   it        ceo

So, the render part is super easy:

    <tbody>
          <tr>
            <th>Name</th>
            <th>Last Name</th>
            <th>Age</th>
            <th>Occupation</th>
          </tr>
          {data.people.map((item, i) => (
            <tr key={i}>
              <td>{item.name}</td>
              <td>{item.last_name}</td>
              <td>{item.age}</td>
              <td>{item.Occupation}</td>
            </tr>
          ))}
    </tbody>

So is the CSS part:

tr {
  display: block;
  float: left;
}
th,td {
  display: block;
  text-align: left;
  padding: 6px;
  border: 1px solid #ccc;
}

That's it. Oh, here is the sandbox.

Sign up to request clarification or add additional context in comments.

3 Comments

Personally, I don't like the "trick" like this. You should normalize the data first.
@Phong You had already posted a way that involved normalizing. Would you rather I repost your answer? Just wanted to give a different solutions to the problem.
Ok, that makes sense, your trick is another option. But there are many ways to normalize data, I think :D.
1

The root problem is, normalize your data from flat data into dynamic/aggregated data by horizontal key & values as the following structure

[
  {
    "Name": [
      "John",
      "Jack",
      "Oliver"
    ]
  },
  {
    "Last Name": [
      "Doe",
      "Brown",
      "Black"
    ]
  },
  {
    "Age": [
      "25",
      "24",
      "30"
    ]
  },
  {
    "Occupation": [
      "driver",
      "it",
      "cto"
    ]
  }
]

const data ={
    "people" :[
      {
        "name":"John",
        "last_name":"Doe",
        "age":"25",
        "Occupation":"driver",
      },
      {
        "name":"Jack",
        "last_name":"Brown",
        "age":"24",
        "Occupation":"it"
      },
      {
        "name":"Oliver",
        "last_name":"Black",

        "age":"30",
        "Occupation":"cto"
      },
    ],

    "format":{"last_name":"Last Name"}
  };
var items  = Object.values(data)[0];

var createOrEdit = (acc, key, value) => {
    var findItem = acc.find(r => r[key] !== undefined);
    if(findItem == undefined)
      acc.push({[key]: [value]});
    else
      findItem[key].push(value);
    
    return acc;
}

var result = items.reduce((acc, curr) => {
    createOrEdit(acc, 'Name', curr.name);
    createOrEdit(acc, 'Last Name', curr.last_name);
    createOrEdit(acc, 'Age', curr.age);    
    createOrEdit(acc, 'Occupation', curr.Occupation);
    
    return acc;
}, [])

console.log(result);
  
for(let item of result){
  console.log(Object.keys(item)[0]);
  console.log(Object.values(item)[0]);
}

After that, you can easily render data based on normalized data like below

const nomorlizeData = (data) => {
  var items = Object.values(data)[0];

  var createOrEdit = (acc, key, value) => {
    var findItem = acc.find((r) => r[key] !== undefined);
    if (findItem === undefined) acc.push({ [key]: [value] });
    else findItem[key].push(value);

    return acc;
  };

  var result = items.reduce((acc, curr) => {
    createOrEdit(acc, "Name", curr.name);
    createOrEdit(acc, "Last Name", curr.last_name);
    createOrEdit(acc, "Age", curr.age);
    createOrEdit(acc, "Occupation", curr.Occupation);

    return acc;
  }, []);

  return result;
};

function App() {
  const data = {
    people: [
      {
        name: "John",
        last_name: "Doe",
        age: "25",
        Occupation: "driver"
      },
      {
        name: "Jack",
        last_name: "Brown",
        age: "24",
        Occupation: "it"
      },
      {
        name: "Oliver",
        last_name: "Black",

        age: "30",
        Occupation: "cto"
      }
    ],

    format: { last_name: "Last Name" }
  };

  var renderData = (items) =>
    items.map((r) => {
      var key = <td>{Object.keys(r)[0]}</td>;
      var values = Object.values(r)[0].map((v) => <td>{v}</td>);
      return (
        <tr>
          {key}
          {values}
        </tr>
      );
    });
  return (
    <div className="App">
      <table>
        <tbody>{renderData(nomorlizeData(data))}</tbody>
      </table>
    </div>
  );
}



ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Codesanbox demo here

5 Comments

hi, sorry to bother, but I have additional question, could you please help me with it? Basically, I forgot to add id to the data, and now I need to add id to each <td> element. I updated CodeSandbox with id. codesandbox.io/s/compassionate-rain-7o2v2 I really appreciate your help, thank you.
Oh, I'm busy now. I'll get back to you soon. Bro. Maybe tmr morning ^^!
Hi @nika, what does the new structure & expected data/result you want to display?
If your expected result is this, You just need to add createOrEdit(acc, "id", curr.id); into your code.
hi, thank you for replying. No, i wanted to add id to the <td> cell, like <td id={id}> value </td>. I don't know if that's possible though.
0

See if this works! https://stackblitz.com/edit/react-ie2rt6

import React from "react";

const Table = ({ headers, data }) => {
  return (
    <div>
      <table>
        <thead>
          <tr>
            {headers.map(head => (
              <th>{head}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {data.map(row => (
            <tr>
              {headers.map(head => (
                <td>{row[head]}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default Table;

2 Comments

Your solution is too complex. Must use too much 3rd lib without knowing behind the sense ==> Too bad for your logical thinking.
Firstly, Your data and structure are irrelevant with OP. Secondly, You should explain some parts involve in your answer. It makes me too hard to be able to understand :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.