Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Reusable Tables in React
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