I'm writing a code in react, where in I want to display the json data in HTML table. I want this to be dynamic. i.e. irrespective of the type of json data I'm using, it should render in tabular format.
Here is my code with sample data.
const jsArray = [{"Model":"Mazda RX4","mpg":21,"cyl":6},{"Model":"Mazda RX4 Wag","mpg":21,"cyl":6},{"Model":"Datsun 710","mpg":22.8,"cyl":""},{"Model":"Hornet 4 Drive","mpg":21.4,"cyl":""},{"Model":"Hornet Sportabout","mpg":18.7,"cyl":8},{"Model":"Valiant","mpg":18.1,"cyl":6}];
{jsArray.length > 0 && (
<table>
<thead>
{jsArray.map((item, idx) =>
idx === 0 ? (
<th key={idx}>
{Object.values(item).forEach((val) => (
<td>{val}</td>
))}
</th>
) : (
<tr key={idx}>
{Object.values(item).forEach((val) => (
<td>{val}</td>
))}
</tr>
)
)}
</thead>
</table>
)}
When I run this code, nothing is getting rendered. When I replace <tr key={idx}>{Object.values(item).forEach((val)=> (<td>{val}</td>))}</tr>
with null
, In my output I see null printed in my front end. Please let me know where I'm going wrong.
You can do it like this:
const data = JSON.parse(jsArray);
const keys = Object.keys(data.length ? data[0] : {});
return (
<div className="App">
{jsArray.length > 0 && (
<table>
<thead>
<tr>
{keys.map((item, idx) => (
<th key={idx}>{item}</th>
))}
</tr>
</thead>
<tbody>
{data.map((item, idx) => (
<tr key={idx}>
{keys.map((key, idx) => (
<td>{item[key]}</td>
))}
</tr>
))}
</tbody>
</table>
)}
</div>
);
It might make it easier if you broke all that logic down into more helpful functions.
getHeadings
maps
over the first object and grabs its keys
.
getRows
maps
over all the data, and calls getCells
with each object's data.
getCells
maps
over the object and uses Object.values
to get the information for each cell.
This way your component is a lot cleaner.
// `map` over the first object in the array
// and get an array of keys and add them
// to TH elements
function getHeadings(data) {
return Object.keys(data[0]).map(key => {
return <th>{key}</th>;
});
}
// `map` over the data to return
// row data, passing in each mapped object
// to `getCells`
function getRows(data) {
return data.map(obj => {
return <tr>{getCells(obj)}</tr>;
});
}
// Return an array of cell data using the
// values of each object
function getCells(obj) {
return Object.values(obj).map(value => {
return <td>{value}</td>;
});
}
// Simple component that gets the
// headers and then the rows
function Example({ data }) {
return (
<table>
<thead>{getHeadings(data)}</thead>
<tbody>{getRows(data)}</tbody>
</table>
);
}
const data = [{"Model":"Mazda RX4","mpg":21,"cyl":6},{"Model":"Mazda RX4 Wag","mpg":21,"cyl":6},{"Model":"Datsun 710","mpg":22.8,"cyl":""},{"Model":"Hornet 4 Drive","mpg":21.4,"cyl":""},{"Model":"Hornet Sportabout","mpg":18.7,"cyl":8},{"Model":"Valiant","mpg":18.1,"cyl":6}];
ReactDOM.render(
<Example data={data} />,
document.getElementById('react')
);
table { border: 1px solid #dfdfdf; border-collapse: collapse; }
th { background-color: #efefef; text-align: left; text-transform: uppercase; }
td { border: 1px solid #efefef; }
td, th { padding: 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>