MUI Table clicks can happen at a variety of component levels. For example, we can have a click handler on a TableCell and a TableRow, and both of them can trigger from the same click.
In this post we’ll look at click handlers on the following MUI components:
- TableCell
- TableRow
- TableHead
- TableContainer
Furthermore, we have a significant amount of data in the click event that can be used in the handler. We’ll explore the values available on the event
object and how they can be used. I will include full TypeScript support.
Material-UI Table onClick With TypeScript
If you are using TypeScript, all the Table components can be typed the same generic way if desired: (e: React.MouseEvent<HTMLElement>) => void
.

Alternatively, each element’s click handler can take a type specific to what kind of element was clicked. Here’s another TableCell click handler: (e: React.MouseEventHandler<HTMLTableCellElement>) => void
.
MUI Table onClick Event Values
In the example below I open an alert on click of the TableHead component.
Take a look at the values present on the event object. Values like cellIndex
and innerHTML
are particularly useful. There is lots of useful data in the event object for whatever your objective is.

In my example, I added a click handler at both the TableHead level and the TableCell level (children inside the TableBody). The JSX is abbreviated below.
export default function StylishTable() {
const [snackbarOpen, setSnackbarOpen] = React.useState(false);
const [infoText, setInfoText] = React.useState("a data");
const tableCellClickHandler =
(e: React.MouseEvent<HTMLElement>) =>
{
console.log((e.target as Element).innerHTML);
};
const tableHeaderClickHandler =
(e: React.MouseEvent<HTMLElement>) =>
{
setSnackbarOpen(true);
if (((e.target as unknown) as Cell).cellIndex) {
setInfoText("data");
} else {
setInfoText("title");
}
};
//JSX snippets
<TableHead onClick={tableHeaderClickHandler} />
//These are cells in the TableBody component
<TableCell onClick={tableCellClickHandler} />
<TableCell onClick={tableCellClickHandler} />
<TableCell onClick={tableCellClickHandler} />
<TableCell onClick={tableCellClickHandler} />
The click handler in the TableHeader could have just as easily been placed on the TableRow that contained all the cells in the header.
The result of the header click handler is that an alert is opened inside a snackbar component. If the cell clicked has an index of zero, then the text in the snackbar displays “This is a title cell”. If the index is greater than zero, then the text displays “This is a data cell”.
The TypeScript typing on the header click handler was challenging. Event targets can be difficult to ‘type’ properly, and the cellIndex value mysteriously gets added to the event target in this click event. Because of this, I simply casted the event target to ‘unknown’ and then casted it as having a cellIndex value. Even if I typed as the more specific HTMLTableSectionElement
the event still did not have cellIndex
.
The click handler on the TableCell is simpler. It can be cast as an Element and then element values such as innerHTML are available. Read this helpful post for more detail on the TypeScript error that occurs if you don’t cast the event target value.
MUI TableCell, TableRow, TableHead, and TableContainer onClick Example
I added a click listener on a cell inside the row inside the header, all of which is inside the TableContainer. The click on the cell bubbled up the DOM as expected and and each handler logged a message sequentially:

Full Code and Related Links
I removed the styling from the code below. Here’s how to set table border, background color, font size, and other styling.
More useful MUI table resources:
- React MUI v5 Table Tutorial: TypeScript, Styling, and Component Cells
- The Ultimate Guide to Material-UI Table Pagination
- The Ultimate Guide To Material-UI Table Row Height
- How to Customize Material-UI Table Scrolling
- The Easiest Way to Implement Material-UI Table Search and Filter
import React from "react";
import Alert from "@mui/material/Alert";
import Snackbar from "@mui/material/Snackbar";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
interface Cell {
cellIndex: number;
}
const tableStyling = {
padding: "0px 0px"
};
function createData(name: string, calories: number, fat: number, carbs: number, protein: number) {
return { name, calories, fat, carbs, protein };
}
const rows = [
createData("Donut", 159, 6.0, 24, 4.0),
createData("Hot Dog", 237, 9.0, 37, 4.3),
createData("Pizza", 262, 16.0, 24, 6.0),
createData("Pie", 305, 3.7, 67, 4.3),
createData("Sandwich", 356, 16.0, 49, 3.9)
];
export default function ClickTable() {
const [snackbarOpen, setSnackbarOpen] = React.useState(false);
const [infoText, setInfoText] = React.useState("a data");
const tableCellClickHandler = (e: React.MouseEvent<HTMLElement>) => {
console.log((e.target as Element).innerHTML);
};
const tableHeaderClickHandler = (e: React.MouseEvent<HTMLElement>) => {
console.log("Detected Header Click");
setSnackbarOpen(true);
if (((e.target as unknown) as Cell).cellIndex) {
setInfoText("data");
} else {
setInfoText("title");
}
};
const handleAlertClose = () => {
setSnackbarOpen(false);
};
return (
<div>
<TableContainer
onClick={() => {
console.log("Detected Table Container Click");
}}
component={Paper}
>
<Table sx={{ tableLayout: "auto" }}>
<TableHead onClick={tableHeaderClickHandler}>
<TableRow
onClick={() => {
console.log("Detected Row Click");
}}
>
<TableCell
onClick={() => {
console.log("Detected Cell Click");
}}
>
Food
</TableCell>
<TableCell sx={{ ...tableStyling, width: 100 }} align="right">
Calories
</TableCell>
<TableCell sx={{ ...tableStyling, width: 100 }} align="right">
Fat
</TableCell>
<TableCell sx={{ ...tableStyling, width: 100 }} align="right">
Carbs
</TableCell>
<TableCell sx={{ ...tableStyling, width: "25%" }} align="right">
Protein
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow key={row.name}>
<TableCell
>
{row.name}
</TableCell>
<TableCell
onClick={tableCellClickHandler}
>
{row.calories}
</TableCell>
<TableCell
onClick={tableCellClickHandler}
>
{row.fat}
</TableCell>
<TableCell
onClick={tableCellClickHandler}
>
{row.carbs}
</TableCell>
<TableCell
onClick={tableCellClickHandler}
>
{row.protein}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<Snackbar
open={snackbarOpen}
autoHideDuration={3000}
onClose={handleAlertClose}
>
<Alert severity="info" sx={{ width: "100%" }}>
This is a {infoText} column.
</Alert>
</Snackbar>
</div>
);
}