One possible solution to make the code more organized and reusable is to create a separate component for the table header and another one for the table row. This way, we can pass the columns and table data as props to these components and avoid repeating the same code for each table.
Here's an example implementation:
// TableHeader.js
function TableHeader({ columns }) {
return (
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
{columns.map((column, index) => (
<th key={index} scope="col" className="px-6 py-3">
{column}
</th>
))}
</tr>
</thead>
);
}
// TableRow.js
function TableRow({ row }) {
return (
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
{Object.values(row).map((value, index) => (
<td key={index} className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
{value}
</td>
))}
</tr>
);
}
// Table.js
function Table({ columns, data }) {
return (
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<TableHeader columns={columns} />
<tbody>
{data.length > 0 ? (
data.map((row, index) => <TableRow key={index} row={row} />)
) : (
<tr>
<td colSpan={columns.length} className="p-6 mx-auto w-max">
Sorry, but we cannot find any tables!
</td>
</tr>
)}
</tbody>
</table>
);
}
To use this component, we can pass the columns and data as props:
<Table columns={columns} data={table} />
This will render the same table as before, but with more organized and reusable code.