Still_Learning
Still_Learning

Reputation: 229

looping and rendering the array of objects

I am trying to loop the data from json and display it it in table. I am having array of objects. I am having 3 values in my json file , I need to display all three data in individual cells, the third column is in array format. So the structure of my json is array of object and inside object my third column is again an array. I am trying to get all the data dynamically, but when I am using map method I am unable to get the values. Hence I tried using Object.Values and forEach, and I am getting the values based on position. Can any one assist me how get all the data dynamically. Thanks in advance. I have pasted the code and mock data below. Thanks in advance!

//I need to display the values in below table component. 
const Table = () => (
  <Table>
    <Header>
      <HeaderCell key="NAME">Contact Name</HeaderCell>
      <HeaderCell key="ContactID">Contact ID</HeaderCell>
      <HeaderCell key="contactGrp">Contact Group</HeaderCell>
    </Header>
    <Body>
      <Row key="conact-0">
        <Cell key="NAME">ABC</Cell>
        <Cell key="ContactID">123</Cell>
        <Cell key="contactGrp">[1, 2]//In badge format</Cell>
      </Row>
    </Body>
  </Table>
);

//Table PROPS- Prop: Children Type: Node (the child content for table consisting of eithera Table Header or Body)
//Table Header Props- Prop: Children Type: node
//Table Row Props - Prop: Children Type: node (child tablecells to be placed within the tr)
//Table Cell Props - Prop: Children Type: node (content to be displayed for row cell)

//My Code
Const customTable = ({mockData})=> {
 return (
   <Table>
   <Header>
    <HeaderCell key="Name"> Contact Name</HeaderCell>
    <HeaderCell key="ID"> Contact ID</HeaderCell>
    <HeaderCell key="Group"> Contact Group</HeaderCell>
  </Header>
  <Body>
  {
    mockData.forEach((element) => {
    console.log(element.key);
    element.cells.forEach(cell => {
        <Row key={cell.key}>
     <Cell  key={cell.key}>{cell.contactName}</Cell>////Here I am not getting the Data
     <Cell  key={cell.key}>{cell.contactID}</Cell>//Here I am not getting the Data
  </Row>

    })
})
}
</Body>

    //MOCK DATA
    const mockData = [
        {
            "key":"row-0",
            "cells":[
    { key: 'cell-0', id: 'ID-0', headerName:'contactname', contactName: 'ABC' },
    { key: 'cell-1', id: 'ID-1', headerName: 'contactID', contactID:'123' },
    { key: 'cell-3', id: 'ID-3', headerName: 'contactGrp', contactGroup: ['A', 'B']}
    ]
    }
    ];
    
   
     

Upvotes: 0

Views: 172

Answers (3)

Nice Books
Nice Books

Reputation: 1861

key values among sibling elements have to be unique, to be rendered correctly.

Inside your element.cells.forEach the 2 <Cell>s have the same key !

Make it:

<Cell  key={cell.key + 'contactName' }>{cell.contactName}</Cell>
<Cell  key={cell.key + 'contactId' }>{cell.contactID}</Cell>

Upvotes: 0

Andy
Andy

Reputation: 63589

It's easier to break it down into steps within the confines of the component. This example utilises three functions to find the headings, all the rows, and the cells for each of those rows.

function Example({ data }) {

  // Return a list of the headings
  function getHeadings(data) {
    return data[0].cells.map(h => {
      return <th>{h.headerName}</th>;
    });
  }

  // Return the cells for a single row
  // making sure that each element of the
  // the array in `contactGroup` is created
  // from a Badge component
  function getRow(cells) {
    return cells.map(cell => {
      const { headerName } = cell;
      if (Array.isArray(cell[headerName])) {
        return (
          <td>
            {cell[headerName].map(el => {
              return <Badge text={el} />;
            })}
          </td>
        );
      }
      return <td>{cell[headerName]}</td>;
    });
  }

  // Get all the rows
  function getRows(data) {
    return data.map(row => {
      return <tr>{getRow(row.cells)}</tr>;
    });
  }

  return (
    <table>
      <thead>{getHeadings(data)}</thead>
      <tbody>{getRows(data)}</tbody>
    </table>
  );

}

// Badge component
function Badge({ text }) {
  return (
    <div className="badge">{text}</div>
  );
}

const data=[{key:"row-0",cells:[{key:"cell-0",id:"ID-0",headerName:"contactName",contactName:"ABC"},{key:"cell-1",id:"ID-1",headerName:"contactID",contactID:"123"},{key:"cell-3",id:"ID-3",headerName:"contactGroup",contactGroup:["A","B"]}]},{key:"row-1",cells:[{key:"cell-1-0",id:"ID-1-0",headerName:"contactName",contactName:"DEF"},{key:"cell-1-1",id:"ID-1-1",headerName:"contactID",contactID:"456"},{key:"cell-1-3",id:"ID-1-3",headerName:"contactGroup",contactGroup:["C","D"]}]}];

ReactDOM.render(
  <Example data={data} />,
  document.getElementById('react')
);
table { border-collapse: collapse; border; 1px solid #565656; }
thead { background-color: #efefef; text-transform: uppercase; }
td, th { padding: 0.5em; border:1px solid #cdcdcd; }
.badge { display: inline; padding: 0.2em 0.4em; background-color: #87CEFA; border: 1px solid #343434; border-radius: 5px; }
.badge:not(:last-child) { margin-right: 0.4em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Upvotes: 1

obscure
obscure

Reputation: 12891

This ain't that hard to do and you even don't need to utilize Object.values first. Just do a .forEach on the object itself and inside the loop do another .forEach on the elements returned from the previous .forEach run.

For example:

const mockData = [{
    "key": "row-0","cells": [{
            key: 'cell-0',
            id: 'ID-0',
            headerName: 'contactname',
            contactName: 'ABC'
        },
        {
            key: 'cell-1',
            id: 'ID-1',
            headerName: 'contactID',
            contactID: '123'
        },
        {
            key: 'cell-3',
            id: 'ID-3',
            headerName: 'contactGrp',
            contactGroup: ['A', 'B']
        }
    ]
}];

mockData.forEach((element) => {
    console.log(element.key);
    element.cells.forEach(cell => {
        console.log(cell.key, cell.id);
    });
});

Upvotes: 0

Related Questions