Design Converter
Education
Last updated on Apr 2, 2025
•13 mins read
Last updated on Apr 2, 2025
•13 mins read
Managing large data sets in React applications requires powerful, flexible, and user-friendly table components. Material UI tables offer the perfect balance of functionality and aesthetics, allowing developers to build data-rich interfaces with minimal effort.
This blog post examines the best Material React Table solutions that can transform how you handle data display in your applications.
Material UI provides a comprehensive set of table components that adhere to Material Design principles. These components allow developers to create great tables and offer advanced features like sorting, filtering, and pagination right out of the box.
At its core, a Material UI table consists of several key elements:
• Table - The main container component
• Table Header - Contains the header row with column headers
• Table Body - Houses the rows of data
• Table Cell - Individual data cells that display information
Let's visualize the structure of a typical Material UI table:
Before we dive into more advanced solutions, let's understand how a basic Material UI table is implemented:
1import React from 'react'; 2import { 3 Table, 4 TableBody, 5 TableCell, 6 TableContainer, 7 TableHead, 8 TableRow, 9 Paper 10} from '@mui/material'; 11 12function BasicTable() { 13 // Sample data array 14 const rows = [ 15 { id: 1, name: 'John Doe', age: 25, role: 'Developer' }, 16 { id: 2, name: 'Jane Smith', age: 32, role: 'Designer' }, 17 { id: 3, name: 'Bob Johnson', age: 45, role: 'Manager' }, 18 ]; 19 20 return ( 21 <TableContainer component={Paper}> 22 <Table> 23 <TableHead> 24 <TableRow> 25 <TableCell>ID</TableCell> 26 <TableCell>Name</TableCell> 27 <TableCell>Age</TableCell> 28 <TableCell>Role</TableCell> 29 </TableRow> 30 </TableHead> 31 <TableBody> 32 {rows.map((row) => ( 33 <TableRow key={row.id}> 34 <TableCell>{row.id}</TableCell> 35 <TableCell>{row.name}</TableCell> 36 <TableCell>{row.age}</TableCell> 37 <TableCell>{row.role}</TableCell> 38 </TableRow> 39 ))} 40 </TableBody> 41 </Table> 42 </TableContainer> 43 ); 44}
This simple example demonstrates how table data is structured and displayed using Material UI table components. However, more robust solutions are needed for applications with complex data requirements.
Material React Table is a powerful library built on Material UI that offers a complete table solution with all the advanced features you might need.
• Column sorting with customizable sort direction
• Advanced filtering options
• Pagination for handling large data sets
• Row selection with row checkboxes
• Support for nested data and tree data structures
• Customizable cell rendering
• Server-side data processing
1import React from 'react'; 2import { MaterialReactTable } from 'material-react-table'; 3 4function AdvancedTable() { 5 // Define columns with appropriate settings 6 const columns = [ 7 { 8 accessorKey: 'id', 9 header: 'ID', 10 enableSorting: true, 11 }, 12 { 13 accessorKey: 'name', 14 header: 'Name', 15 enableSorting: true, 16 enableFiltering: true, 17 }, 18 { 19 accessorKey: 'age', 20 header: 'Age', 21 enableSorting: true, 22 }, 23 { 24 accessorKey: 'role', 25 header: 'Role', 26 enableSorting: true, 27 enableFiltering: true, 28 }, 29 ]; 30 31 // Sample data array 32 const data = [ 33 { id: 1, name: 'John Doe', age: 25, role: 'Developer' }, 34 { id: 2, name: 'Jane Smith', age: 32, role: 'Designer' }, 35 { id: 3, name: 'Bob Johnson', age: 45, role: 'Manager' }, 36 ]; 37 38 return ( 39 <MaterialReactTable 40 columns={columns} 41 data={data} 42 enableRowSelection 43 enableColumnFiltering 44 enableSorting 45 enablePagination 46 initialState={{ 47 pagination: { 48 pageSize: 10, 49 pageIndex: 0, 50 }, 51 }} 52 /> 53 ); 54}
MUI-Datatables is another popular choice that extends Material UI tables with additional functionality.
• Responsive design for various screen sizes
• Built-in search bar functionality
• Customizable filtering options
• Multiple row selection with checkboxes
• Custom rendering for column headers and cells
• Export options (CSV, PDF)
1import React from 'react'; 2import MUIDataTable from 'mui-datatables'; 3 4function MuiDataTable() { 5 const columns = [ 6 { 7 name: 'id', 8 label: 'ID', 9 options: { 10 sort: true, 11 }, 12 }, 13 { 14 name: 'name', 15 label: 'Name', 16 options: { 17 sort: true, 18 filter: true, 19 }, 20 }, 21 { 22 name: 'age', 23 label: 'Age', 24 options: { 25 sort: true, 26 }, 27 }, 28 { 29 name: 'role', 30 label: 'Role', 31 options: { 32 sort: true, 33 filter: true, 34 }, 35 }, 36 ]; 37 38 const data = [ 39 [1, 'John Doe', 25, 'Developer'], 40 [2, 'Jane Smith', 32, 'Designer'], 41 [3, 'Bob Johnson', 45, 'Manager'], 42 ]; 43 44 const options = { 45 filterType: 'dropdown', 46 responsive: 'standard', 47 selectableRows: 'multiple', 48 rowsPerPage: 10, 49 page: 0, 50 }; 51 52 return ( 53 <MUIDataTable 54 title="Employee Data" 55 data={data} 56 columns={columns} 57 options={options} 58 /> 59 ); 60}
Combining the flexibility of React-Table with Material UI styling provides a highly customizable solution:
1import React from 'react'; 2import { useTable, useSorting, useFilters, usePagination } from 'react-table'; 3import { 4 Table, 5 TableBody, 6 TableCell, 7 TableContainer, 8 TableHead, 9 TableRow, 10 Paper, 11 TablePagination, 12} from '@mui/material'; 13 14function ReactTableWithMUI() { 15 const columns = React.useMemo( 16 () => [ 17 { 18 Header: 'ID', 19 accessor: 'id', 20 }, 21 { 22 Header: 'Name', 23 accessor: 'name', 24 }, 25 { 26 Header: 'Age', 27 accessor: 'age', 28 }, 29 { 30 Header: 'Role', 31 accessor: 'role', 32 }, 33 ], 34 [] 35 ); 36 37 const data = React.useMemo( 38 () => [ 39 { id: 1, name: 'John Doe', age: 25, role: 'Developer' }, 40 { id: 2, name: 'Jane Smith', age: 32, role: 'Designer' }, 41 { id: 3, name: 'Bob Johnson', age: 45, role: 'Manager' }, 42 ], 43 [] 44 ); 45 46 const { 47 getTableProps, 48 getTableBodyProps, 49 headerGroups, 50 page, 51 prepareRow, 52 pageCount, 53 gotoPage, 54 setPageSize, 55 state: { pageIndex, pageSize }, 56 } = useTable( 57 { 58 columns, 59 data, 60 initialState: { pageIndex: 0, pageSize: 10 }, 61 }, 62 useSorting, 63 useFilters, 64 usePagination 65 ); 66 67 const handleChangePage = (event, newPage) => { 68 gotoPage(newPage); 69 }; 70 71 const handleChangeRowsPerPage = (event) => { 72 setPageSize(parseInt(event.target.value, 10)); 73 }; 74 75 return ( 76 <Paper> 77 <TableContainer> 78 <Table {...getTableProps()}> 79 <TableHead> 80 {headerGroups.map((headerGroup) => ( 81 <TableRow {...headerGroup.getHeaderGroupProps()}> 82 {headerGroup.headers.map((column) => ( 83 <TableCell {...column.getHeaderProps()}> 84 {column.render('Header')} 85 </TableCell> 86 ))} 87 </TableRow> 88 ))} 89 </TableHead> 90 <TableBody {...getTableBodyProps()}> 91 {page.map((row) => { 92 prepareRow(row); 93 return ( 94 <TableRow {...row.getRowProps()}> 95 {row.cells.map((cell) => ( 96 <TableCell {...cell.getCellProps()}> 97 {cell.render('Cell')} 98 </TableCell> 99 ))} 100 </TableRow> 101 ); 102 })} 103 </TableBody> 104 </Table> 105 </TableContainer> 106 <TablePagination 107 component="div" 108 count={data.length} 109 page={pageIndex} 110 onPageChange={handleChangePage} 111 rowsPerPage={pageSize} 112 onRowsPerPageChange={handleChangeRowsPerPage} 113 /> 114 </Paper> 115 ); 116}
Row selection is a common requirement in data management interfaces. With Material React Table, implementing row selection with checkboxes is straightforward:
1<MaterialReactTable 2 columns={columns} 3 data={data} 4 enableRowSelection 5 onRowSelectionChange={setRowSelection} 6 state={{ rowSelection }} 7/>
This allows users to select one or multiple rows for batch operations. The component provides both API methods and UI elements to manage row selection effectively.
For complex data display needs, custom cell rendering is invaluable:
1const columns = [ 2 // ... other columns 3 { 4 accessorKey: 'status', 5 header: 'Status', 6 Cell: ({ cell }) => ( 7 <div> 8 {cell.getValue() === 'active' ? ( 9 <Chip color="success" label="Active" /> 10 ) : ( 11 <Chip color="error" label="Inactive" /> 12 )} 13 </div> 14 ), 15 }, 16 { 17 accessorKey: 'actions', 18 header: 'Actions', 19 Cell: ({ row }) => ( 20 <div> 21 <IconButton onClick={() => handleEdit(row.original)}> 22 <EditIcon /> 23 </IconButton> 24 <IconButton onClick={() => handleDelete(row.original.id)}> 25 <DeleteIcon /> 26 </IconButton> 27 </div> 28 ), 29 }, 30];
This example shows how to render custom status indicators and action buttons within table cells.
Material React Table provides sophisticated filtering capabilities:
Implementation example:
1const columns = [ 2 { 3 accessorKey: 'name', 4 header: 'Name', 5 filterFn: 'contains', 6 }, 7 { 8 accessorKey: 'age', 9 header: 'Age', 10 filterFn: 'between', 11 }, 12 { 13 accessorKey: 'date', 14 header: 'Date', 15 filterFn: 'dateBetween', 16 } 17]; 18 19<MaterialReactTable 20 columns={columns} 21 data={data} 22 enableColumnFiltering 23 enableGlobalFilter 24 initialState={{ 25 columnFilters: [ 26 { 27 id: 'name', 28 value: 'John', 29 }, 30 ], 31 }} 32/>
For complex data structures, Material React Table offers excellent support for nested data:
1const data = [ 2 { 3 id: 1, 4 name: 'John Doe', 5 details: { 6 address: { 7 street: '123 Main St', 8 city: 'Boston', 9 state: 'MA', 10 }, 11 contact: { 12 email: 'john@example.com', 13 phone: '555-1234', 14 }, 15 }, 16 }, 17 // More data... 18]; 19 20const columns = [ 21 { 22 accessorKey: 'id', 23 header: 'ID', 24 }, 25 { 26 accessorKey: 'name', 27 header: 'Name', 28 }, 29 { 30 accessorKey: 'details.address.city', 31 header: 'City', 32 }, 33 { 34 accessorKey: 'details.contact.email', 35 header: 'Email', 36 }, 37];
This approach lets you access deeply nested properties using dot notation in the accessorKey.
When working with large data sets, performance becomes a critical concern. Here are some strategies to optimize Material UI table performance:
For tables with thousands of rows, virtual scrolling can significantly improve performance by rendering only visible rows:
1<MaterialReactTable 2 columns={columns} 3 data={largeDataArray} 4 enablePagination={false} 5 enableVirtualization 6 muiTableContainerProps={{ sx: { maxHeight: '600px' } }} 7/>
For extremely large data sets, server-side processing is recommended:
1function ServerSideTable() { 2 const [data, setData] = useState([]); 3 const [loading, setLoading] = useState(false); 4 const [pagination, setPagination] = useState({ 5 pageIndex: 0, 6 pageSize: 10, 7 }); 8 const [sorting, setSorting] = useState([]); 9 const [columnFilters, setColumnFilters] = useState([]); 10 11 useEffect(() => { 12 const fetchData = async () => { 13 setLoading(true); 14 // Construct query parameters based on pagination, sorting, and filtering state 15 const queryParams = new URLSearchParams({ 16 page: pagination.pageIndex, 17 size: pagination.pageSize, 18 sort: sorting.length > 0 ? `${sorting[0].id}:${sorting[0].desc ? 'desc' : 'asc'}` : '', 19 // Add filter parameters 20 }); 21 22 const response = await fetch(`/api/data?${queryParams}`); 23 const json = await response.json(); 24 25 setData(json.data); 26 setLoading(false); 27 }; 28 29 fetchData(); 30 }, [pagination, sorting, columnFilters]); 31 32 return ( 33 <MaterialReactTable 34 columns={columns} 35 data={data} 36 enableRowSelection 37 manualPagination 38 manualSorting 39 manualFiltering 40 onPaginationChange={setPagination} 41 onSortingChange={setSorting} 42 onColumnFiltersChange={setColumnFilters} 43 state={{ 44 pagination, 45 sorting, 46 columnFilters, 47 isLoading: loading, 48 }} 49 rowCount={10000} // Total number of rows from server 50 /> 51 ); 52}
Let's compare the top Material UI table solutions based on key features:
Feature | Material React Table | MUI-Datatables | React-Table with MUI |
---|---|---|---|
Sorting | ✅ Advanced | ✅ Basic | ✅ Customizable |
Filtering | ✅ Advanced | ✅ Basic | ✅ Customizable |
Pagination | ✅ Built-in | ✅ Built-in | ✅ Manual Implementation |
Row Selection | ✅ Checkbox + API | ✅ Checkbox | ✅ Manual Implementation |
Custom Cell Rendering | ✅ Simple API | ✅ Basic | ✅ Fully Customizable |
Nested Data | ✅ Built-in Support | ⚠️ Limited | ✅ Manual Implementation |
Tree Data | ✅ Built-in | ❌ Not Supported | ⚠️ Complex Implementation |
Server-side Processing | ✅ Built-in | ✅ Basic | ✅ Manual Implementation |
Bundle Size | ⚠️ Larger | ✅ Medium | ✅ Smaller (modular) |
Ease of Use | ✅ Simple API | ✅ Simple API | ⚠️ More Code Required |
Let's build a comprehensive example using Material React Table with sorting, filtering, pagination, and row selection:
1import React, { useState } from 'react'; 2import { MaterialReactTable } from 'material-react-table'; 3import { Button, Box, Tooltip, IconButton } from '@mui/material'; 4import DeleteIcon from '@mui/icons-material/Delete'; 5import EditIcon from '@mui/icons-material/Edit'; 6 7function CompleteDataTable() { 8 const [rowSelection, setRowSelection] = useState({}); 9 10 const columns = [ 11 { 12 accessorKey: 'id', 13 header: 'ID', 14 enableSorting: true, 15 size: 100, 16 }, 17 { 18 accessorKey: 'name', 19 header: 'Name', 20 enableSorting: true, 21 enableFiltering: true, 22 size: 150, 23 filterFn: 'contains', 24 }, 25 { 26 accessorKey: 'email', 27 header: 'Email', 28 enableSorting: true, 29 enableFiltering: true, 30 size: 200, 31 }, 32 { 33 accessorKey: 'role', 34 header: 'Role', 35 enableSorting: true, 36 enableFiltering: true, 37 size: 150, 38 filterFn: 'equals', 39 filterSelectOptions: [ 40 { text: 'Admin', value: 'admin' }, 41 { text: 'User', value: 'user' }, 42 { text: 'Manager', value: 'manager' }, 43 ], 44 filterVariant: 'select', 45 }, 46 { 47 accessorKey: 'status', 48 header: 'Status', 49 enableSorting: true, 50 enableFiltering: true, 51 filterVariant: 'select', 52 filterSelectOptions: [ 53 { text: 'Active', value: 'active' }, 54 { text: 'Inactive', value: 'inactive' }, 55 ], 56 Cell: ({ cell }) => ( 57 <span 58 style={{ 59 color: cell.getValue() === 'active' ? 'green' : 'red', 60 fontWeight: 'bold', 61 }} 62 > 63 {cell.getValue()} 64 </span> 65 ), 66 }, 67 { 68 accessorKey: 'lastLogin', 69 header: 'Last Login', 70 enableSorting: true, 71 Cell: ({ cell }) => new Date(cell.getValue()).toLocaleString(), 72 }, 73 { 74 id: 'actions', 75 header: 'Actions', 76 enableSorting: false, 77 enableFiltering: false, 78 Cell: ({ row }) => ( 79 <Box sx={{ display: 'flex' }}> 80 <Tooltip title="Edit"> 81 <IconButton onClick={() => handleEdit(row.original)}> 82 <EditIcon /> 83 </IconButton> 84 </Tooltip> 85 <Tooltip title="Delete"> 86 <IconButton color="error" onClick={() => handleDelete(row.original.id)}> 87 <DeleteIcon /> 88 </IconButton> 89 </Tooltip> 90 </Box> 91 ), 92 }, 93 ]; 94 95 // Sample data array 96 const data = [ 97 { 98 id: 1, 99 name: 'John Smith', 100 email: 'john@example.com', 101 role: 'admin', 102 status: 'active', 103 lastLogin: '2025-03-15T10:30:00', 104 }, 105 { 106 id: 2, 107 name: 'Jane Doe', 108 email: 'jane@example.com', 109 role: 'user', 110 status: 'active', 111 lastLogin: '2025-03-10T08:45:00', 112 }, 113 { 114 id: 3, 115 name: 'Bob Johnson', 116 email: 'bob@example.com', 117 role: 'manager', 118 status: 'inactive', 119 lastLogin: '2025-02-28T16:20:00', 120 }, 121 // More data rows... 122 ]; 123 124 const handleEdit = (rowData) => { 125 console.log('Edit row:', rowData); 126 // Implement edit functionality 127 }; 128 129 const handleDelete = (id) => { 130 console.log('Delete row with ID:', id); 131 // Implement delete functionality 132 }; 133 134 const handleBulkDelete = () => { 135 const selectedIds = Object.keys(rowSelection).map( 136 (index) => data[parseInt(index)].id 137 ); 138 console.log('Delete selected rows with IDs:', selectedIds); 139 // Implement bulk delete functionality 140 }; 141 142 return ( 143 <Box sx={{ p: 2 }}> 144 <MaterialReactTable 145 columns={columns} 146 data={data} 147 enableRowSelection 148 enableColumnFiltering 149 enableGlobalFilter 150 enablePagination 151 enableSorting 152 enableColumnResizing 153 enableColumnOrdering 154 onRowSelectionChange={setRowSelection} 155 state={{ rowSelection }} 156 positionToolbarAlertBanner="bottom" 157 renderTopToolbarCustomActions={({ table }) => ( 158 <Box sx={{ display: 'flex', gap: 2, p: 1 }}> 159 <Button 160 variant="contained" 161 color="primary" 162 onClick={() => console.log('Add new user')} 163 > 164 Add New 165 </Button> 166 <Button 167 variant="contained" 168 color="error" 169 disabled={Object.keys(rowSelection).length === 0} 170 onClick={handleBulkDelete} 171 > 172 Delete Selected 173 </Button> 174 </Box> 175 )} 176 muiTablePaginationProps={{ 177 rowsPerPageOptions: [5, 10, 25, 50, 100], 178 showFirstButton: true, 179 showLastButton: true, 180 }} 181 initialState={{ 182 pagination: { 183 pageSize: 10, 184 pageIndex: 0, 185 }, 186 sorting: [ 187 { 188 id: 'name', 189 desc: false, 190 }, 191 ], 192 }} 193 /> 194 </Box> 195 ); 196}
This example incorporates many of the advanced features discussed and shows how to build a complete data management interface with Material React Table.
Define columns with appropriate configuration options:
1const columns = [ 2 { 3 accessorKey: 'id', 4 header: 'ID', 5 enableSorting: true, 6 enableFiltering: false, // No need to filter IDs typically 7 size: 80, // Fixed width for ID column 8 }, 9 { 10 accessorKey: 'name', 11 header: 'Name', 12 enableSorting: true, 13 enableFiltering: true, 14 minSize: 150, // Minimum width 15 maxSize: 300, // Maximum width 16 }, 17 // More columns... 18];
• Use virtualization for large data sets
• Implement server-side processing when necessary
• Memoize columns and data definitions
• Use appropriate rendering techniques for complex cells
• Implement responsive design for mobile users
• Add meaningful tooltips for actions and complex data
• Use consistent icon patterns for actions
• Provide clear visual cues for interactive elements
1// Example of column header with tooltip 2{ 3 accessorKey: 'priority', 4 header: () => ( 5 <Tooltip title="Task priority level affects scheduling"> 6 <div>Priority Level</div> 7 </Tooltip> 8 ), 9 // Other configuration 10}
For complex tables with many features enabled, state management becomes crucial:
1function OptimizedTable() { 2 // Memoize columns definition 3 const columns = React.useMemo(() => [ 4 // Column definitions 5 ], []); 6 7 // Memoize data when it doesn't change frequently 8 const data = React.useMemo(() => [ 9 // Data array 10 ], []); 11 12 // Use state for various table features 13 const [pagination, setPagination] = useState({ 14 pageIndex: 0, 15 pageSize: 10, 16 }); 17 const [sorting, setSorting] = useState([]); 18 const [rowSelection, setRowSelection] = useState({}); 19 const [columnFilters, setColumnFilters] = useState([]); 20 21 return ( 22 <MaterialReactTable 23 columns={columns} 24 data={data} 25 onPaginationChange={setPagination} 26 onSortingChange={setSorting} 27 onRowSelectionChange={setRowSelection} 28 onColumnFiltersChange={setColumnFilters} 29 state={{ 30 pagination, 31 sorting, 32 rowSelection, 33 columnFilters, 34 }} 35 // Other props 36 /> 37 ); 38}
Material UI table components offer powerful solutions for managing and displaying data in React applications. From basic tables to advanced data grids with sorting, filtering, and row selection, the ecosystem provides tools for every level of complexity.
Material React Table is a comprehensive solution that combines ease of use with powerful features, making it an excellent choice for most projects. Alternatives like MUI-Datatables or custom implementations with React-Table can also be effective for specific needs.
By leveraging these table components, developers can create intuitive, performant data management interfaces that align with Material Design principles while meeting complex business requirements.
Remember that the right table solution depends on your specific project needs. When making your choice, consider factors like data volume, feature requirements, and performance constraints.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.