Created
September 9, 2021 13:40
-
-
Save r0bc4ry/8599ea9c7ac6f326912fd196e88f7f66 to your computer and use it in GitHub Desktop.
Reusable Tables in React
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from "react"; | |
import { | |
Table, | |
TableBody, | |
TableCell, | |
TableContainer, | |
TableHead, | |
TableRow, | |
} from "@material-ui/core"; | |
/** | |
* An interface defining our general table properties that aren't specific to an single column. | |
* | |
* data: our data | |
* columns: an array of Column objects, determining how we display our data | |
* noDataElement: what should be shown when we don't have any data | |
* onRowClick: what should happen, if anything, when clicking a row in our table | |
*/ | |
interface TableProps { | |
data: any[]; | |
columns: Column[]; | |
noDataElement?: JSX.Element; | |
onRowClick?: (currentValue: any) => void; | |
} | |
/** | |
* An interface defining a single column and how it's displayed. | |
* | |
* headElement: the JSX.Element shown in the head of our column | |
* bodyElement: the JSX.ELement shown in each body cell of our column | |
* width: the width of the column | |
* sortBy: what property in our data object should this column be sorted by, if any | |
*/ | |
interface Column { | |
headElement?: JSX.Element; | |
bodyElement: (data) => JSX.Element; | |
width?: string; | |
sortBy?: string; | |
} | |
const DataTable: React.FC<TableProps> = ({ | |
data, | |
columns, | |
noDataElement, | |
onRowClick, | |
}) => { | |
const [sortBy, setSortBy] = useState<string>(); | |
// TODO This is just a very basic example, you'll most likely want to replace this with your own sorting function | |
const sortedData = data.sort(function (a, b) { | |
return a[sortBy] - b[sortBy]; | |
}); | |
return ( | |
<TableContainer> | |
<Table> | |
<colgroup> | |
{columns.map((column) => { | |
return column.width ? <col width={column.width} /> : <col />; | |
})} | |
</colgroup> | |
<TableHead> | |
<TableRow> | |
{columns.map((column) => ( | |
<TableCell> | |
<div>{column.headElement}</div> | |
{column.sortBy && ( | |
<div onClick={setSortBy(column.sortBy)}> | |
{/* TODO Place your sorting icon(s) here. */} | |
</div> | |
)} | |
</TableCell> | |
))} | |
</TableRow> | |
</TableHead> | |
<TableBody> | |
{sortedData.length === 0 && ( | |
<TableRow> | |
<TableCell colSpan={columns.length}>{noDataElement}</TableCell> | |
</TableRow> | |
)} | |
{sortedData.length > 0 && | |
sortedData.map((currentValue) => ( | |
<TableRow onClick={() => onRowClick && onRowClick(currentValue)}> | |
{columns.map((column) => ( | |
<TableCell>{column.bodyElement(currentValue)}</TableCell> | |
))} | |
</TableRow> | |
))} | |
</TableBody> | |
</Table> | |
</TableContainer> | |
); | |
}; | |
export default DataTable; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How should I call this component? can you have a sample for this one? thank you