Custom Headless Example
For advanced use cases where you want to be in 100% control of your UI components, you can use Material React Table in a more headless way, kind of like how you would use stock TanStack Table.
The power and flexibility here is almost limitless, as you can combine some already built-in Material React Table components alongside your own custom components. For the MRT components to work properly, all you need to do is pass the table
object returned from the useMaterialReactTable
hook.
My Custom Headless Table
5
First Name | Last Name | Address | City | State | |
---|---|---|---|---|---|
Christopher | Lee | 555 Cedar Street | Seattle | Washington | |
Rachel | Anderson | 987 Walnut Court | New York | New York | |
David | Garcia | 654 Maple Avenue | Los Angeles | California | |
Zachary | Davis | 261 Battle Ford | Columbus | Ohio | |
Robert | Smith | 566 Brakus Inlet | Westerville | West Virginia |
1import {2 MRT_GlobalFilterTextField,3 MRT_TableBodyCellValue,4 MRT_TablePagination,5 MRT_ToolbarAlertBanner,6 flexRender,7 type MRT_ColumnDef,8 useMaterialReactTable,9} from 'material-react-table';10import {11 Box,12 Stack,13 Table,14 TableBody,15 TableCell,16 TableContainer,17 TableHead,18 TableRow,19 Typography,20} from '@mui/material';21import { type Person, data } from './makeData';2223const columns: MRT_ColumnDef<Person>[] = [24 {25 accessorKey: 'name.firstName',26 header: 'First Name',27 },28 {29 accessorKey: 'name.lastName',30 header: 'Last Name',31 },32 {33 accessorKey: 'address',34 header: 'Address',35 },36 {37 accessorKey: 'city',38 header: 'City',39 },40 {41 accessorKey: 'state',42 header: 'State',43 },44];4546const Example = () => {47 const table = useMaterialReactTable({48 columns,49 data, //must be memoized or stable (useState, useMemo, defined outside of this component, etc.)50 //MRT display columns can still work, optionally override cell renders with `displayColumnDefOptions`51 enableRowSelection: true,52 initialState: {53 pagination: { pageSize: 5, pageIndex: 0 },54 showGlobalFilter: true,55 },56 //customize the MRT components57 muiPaginationProps: {58 rowsPerPageOptions: [5, 10, 15],59 variant: 'outlined',60 },61 paginationDisplayMode: 'pages',62 });6364 return (65 <Stack sx={{ m: '2rem 0' }}>66 <Typography variant="h4">My Custom Headless Table</Typography>67 <Box68 sx={{69 display: 'flex',70 justifyContent: 'space-between',71 alignItems: 'center',72 }}73 >74 {/**75 * Use MRT components along side your own markup.76 * They just need the `table` instance passed as a prop to work!77 */}78 <MRT_GlobalFilterTextField table={table} />79 <MRT_TablePagination table={table} />80 </Box>81 {/* Using Vanilla Material-UI Table components here */}82 <TableContainer>83 <Table>84 {/* Use your own markup, customize however you want using the power of TanStack Table */}85 <TableHead>86 {table.getHeaderGroups().map((headerGroup) => (87 <TableRow key={headerGroup.id}>88 {headerGroup.headers.map((header) => (89 <TableCell align="center" variant="head" key={header.id}>90 {header.isPlaceholder91 ? null92 : flexRender(93 header.column.columnDef.Header ??94 header.column.columnDef.header,95 header.getContext(),96 )}97 </TableCell>98 ))}99 </TableRow>100 ))}101 </TableHead>102 <TableBody>103 {table.getRowModel().rows.map((row, rowIndex) => (104 <TableRow key={row.id} selected={row.getIsSelected()}>105 {row.getVisibleCells().map((cell, _columnIndex) => (106 <TableCell align="center" variant="body" key={cell.id}>107 {/* Use MRT's cell renderer that provides better logic than flexRender */}108 <MRT_TableBodyCellValue109 cell={cell}110 table={table}111 staticRowIndex={rowIndex} //just for batch row selection to work112 />113 </TableCell>114 ))}115 </TableRow>116 ))}117 </TableBody>118 </Table>119 </TableContainer>120 <MRT_ToolbarAlertBanner stackAlertBanner table={table} />121 </Stack>122 );123};124125export default Example;126
View Extra Storybook Examples