Im trying to create a dynamic table using react.
Here is what I have so far…
DataTable.js
import React from 'react'
import data from '../data/customerData.json'
import '../styles/dataTable.css'
const DataTable = () => {
return (
<div>
{data.map(dat => {
return (
<div>
<table className='data-table-container'>
<tr>
<th>Customer Name</th>
<th>Phone Number</th>
<th>Loan Vehicle</th>
<th>Time Out</th>
<th>Time Due</th>
</tr>
<tr>
<td>{dat.CustomerName}</td>
<td>{dat.PhoneNumber}</td>
<td>{dat.LoanVehicle}</td>
<td>{dat.TimeOut}</td>
<td>{dat.TimeDue}</td>
</tr>
</table>
</div>
);
})}
</div>
);
}
export default DataTable
Home.js
import React, { useState } from 'react';
import Calendar from 'react-calendar';
import DataTable from '../components/DataTable';
import '../styles/calendar.css'
const Home = () => {
const [value, onChange] = useState(new Date());
let today = new Date().toDateString()
return (
<>
<div className='date-display'>
<h3 className='current-date-display'>{today}</h3>
</div>
<Calendar onChange={onChange} value={value} />
<DataTable/>
</>
)
}
export default Home
Here is what that renders in the browser..
So currently in my DataTable.js component I am using .map to loop over the data in customerData.json which works fine. The issue I have is as you can see from the screenshot img the table headers in the <th> tags render with each loop.
My question is how can I display the <th> tags once and keep the loop to display the <td> tag content..
See expected output below..
>Solution :
You’re creating many tables, in a loop. Instead of outputting the entire table in the .map() body, only output the rows. Keep everything else static outside of that loop:
return (
<div>
<div>
<table className='data-table-container'>
<tr>
<th>Customer Name</th>
<th>Phone Number</th>
<th>Loan Vehicle</th>
<th>Time Out</th>
<th>Time Due</th>
</tr>
{data.map(dat => {
return (
<tr>
<td>{dat.CustomerName}</td>
<td>{dat.PhoneNumber}</td>
<td>{dat.LoanVehicle}</td>
<td>{dat.TimeOut}</td>
<td>{dat.TimeDue}</td>
</tr>
);
})}
</table>
</div>
</div>
);
You can make it a little more clear for yourself by explicitly separating <thead> and <tbody> elements:
return (
<div>
<div>
<table className='data-table-container'>
<thead>
<tr>
<th>Customer Name</th>
<th>Phone Number</th>
<th>Loan Vehicle</th>
<th>Time Out</th>
<th>Time Due</th>
</tr>
</thead>
<tbody>
{data.map(dat => {
return (
<tr>
<td>{dat.CustomerName}</td>
<td>{dat.PhoneNumber}</td>
<td>{dat.LoanVehicle}</td>
<td>{dat.TimeOut}</td>
<td>{dat.TimeDue}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
You might even add a default "no records found" row when there’s no data to display, just for a bit more user experience:
return (
<div>
<div>
<table className='data-table-container'>
<thead>
<tr>
<th>Customer Name</th>
<th>Phone Number</th>
<th>Loan Vehicle</th>
<th>Time Out</th>
<th>Time Due</th>
</tr>
</thead>
<tbody>
{data.length > 0 ? data.map(dat => {
return (
<tr>
<td>{dat.CustomerName}</td>
<td>{dat.PhoneNumber}</td>
<td>{dat.LoanVehicle}</td>
<td>{dat.TimeOut}</td>
<td>{dat.TimeDue}</td>
</tr>
);
}) : <tr><td colspan="5">No records found</td></tr>}
</tbody>
</table>
</div>
</div>
);

