Claude-skill-registry-data materialreacttable-mastery
Material React Table V3 expert skill. Use when building feature-rich data tables w/ MUI styling, server-side ops, CRUD editing, virtualization, or complex filtering/sorting.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry-data
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/materialreacttable-mastery" ~/.claude/skills/majiayu000-claude-skill-registry-data-materialreacttable-mastery && rm -rf "$T"
manifest:
data/materialreacttable-mastery/SKILL.mdsource content
Material React Table Mastery
Build production-grade data tables w/ MRT V3 (TanStack Table V8 + MUI).
When to Use
- Building data tables with MUI styling
- Server-side pagination/filtering/sorting
- CRUD editing (inline, modal, cell, table)
- Large dataset virtualization (10k+ rows)
- Complex filtering (date range, multi-select, faceted)
- Migrating between MRT versions (V1→V2→V3)
- MUI v7 compatibility issues
Triggers
- Initialize MRT setup w/ dependencies/mrt-init
- Generate typed column definitions/mrt-column
- Add CRUD editing capabilities/mrt-crud
- Configure server-side pagination/filtering/sorting/mrt-server
- Migrate between MRT versions (V1→V2→V3)/mrt-migrate
- State management, persistence, controlled state/mrt-state
- Data export (CSV, Excel, PDF)/mrt-export
- Accessibility & keyboard navigation setup/mrt-a11y
Reference Files
| Category | Reference | When to Load |
|---|---|---|
| Columns | | Accessors, formatters, grouping, aggregation, V1→V2→V3 migration |
| Filtering | | Filter variants, global search, faceted |
| Pagination | | Server-side, infinite scroll, virtualization |
| Editing | | Inline, modal, row, cell, validation |
| Selection | | Multi-select, actions, bulk ops |
| Tree | | Hierarchical data, expand/collapse |
| Custom | | Toolbar, styling, mrtTheme, localization, z-index |
| State | | Table/row/cell APIs, state persistence, events |
| Advanced | | A11y, export, drag & drop, click-to-copy |
| Versions | | Version matrix, migrations, prop renames |
Core Tenets
1. TanStack Table Foundation
MRT wraps TanStack Table V8. Use
useMaterialReactTable hook for full control.
import { useMaterialReactTable, MaterialReactTable } from 'material-react-table'; const table = useMaterialReactTable({ columns, data, enableColumnFilters: true, enableGlobalFilter: true, enablePagination: true, }); return <MaterialReactTable table={table} />;
2. Column Definitions in useMemo
ALWAYS wrap columns in
useMemo to prevent unnecessary re-renders.
const columns = useMemo<MRT_ColumnDef<Person>[]>(() => [ { accessorKey: 'name', header: 'Name', size: 200 }, { accessorFn: (row) => `${row.firstName} ${row.lastName}`, id: 'fullName', header: 'Full Name', }, { accessorKey: 'status', header: 'Status', filterVariant: 'select', filterSelectOptions: ['Active', 'Inactive', 'Pending'], Cell: ({ cell }) => ( <Chip label={cell.getValue<string>()} color={cell.getValue() === 'Active' ? 'success' : 'default'} /> ), }, { accessorKey: 'salary', header: 'Salary', filterVariant: 'range-slider', Cell: ({ cell }) => cell.getValue<number>().toLocaleString('en-US', { style: 'currency', currency: 'USD', }), aggregationFn: 'sum', AggregatedCell: ({ cell }) => `Total: ${cell.getValue()}`, }, ], []);
3. Server-Side Operations
For datasets > 100 rows, use server-side pagination/filtering/sorting.
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); const [sorting, setSorting] = useState<MRT_SortingState>([]); const [globalFilter, setGlobalFilter] = useState(''); const { data, isLoading } = useQuery({ queryKey: ['users', pagination, sorting, globalFilter], queryFn: () => fetchUsers({ pagination, sorting, globalFilter }), }); const table = useMaterialReactTable({ columns, data: data?.rows ?? [], rowCount: data?.totalCount ?? 0, manualPagination: true, manualSorting: true, manualFiltering: true, state: { pagination, sorting, globalFilter, isLoading }, onPaginationChange: setPagination, onSortingChange: setSorting, onGlobalFilterChange: setGlobalFilter, });
4. CRUD Editing
Support inline, modal, cell, or table editing modes.
const table = useMaterialReactTable({ columns, data, enableEditing: true, editDisplayMode: 'row', // 'modal' | 'cell' | 'table' onEditingRowSave: async ({ values, row, table }) => { await updateUser(row.original.id, values); table.setEditingRow(null); }, renderRowActions: ({ row, table }) => ( <Box sx={{ display: 'flex', gap: '1rem' }}> <Tooltip title="Edit"> <IconButton onClick={() => table.setEditingRow(row)}> <EditIcon /> </IconButton> </Tooltip> <Tooltip title="Delete"> <IconButton color="error" onClick={() => handleDelete(row.original.id)}> <DeleteIcon /> </IconButton> </Tooltip> </Box> ), });
5. Virtualization for Large Data
Enable row virtualization for 10,000+ rows.
const table = useMaterialReactTable({ columns, data: largeDataset, enableRowVirtualization: true, rowVirtualizerOptions: { overscan: 5 }, muiTableBodyRowProps: { sx: { height: 53 } }, // Fixed height for perf });
Decision Tree
Dataset size? ├─ < 100 rows → Client-side (default) ├─ 100-10,000 rows → Server-side pagination └─ > 10,000 rows → Virtualization + server-side
Common Configurations
| Use Case | Configuration |
|---|---|
| Basic display | |
| Editable | |
| Selection | |
| Expandable | |
| Tree data | |
| Server-side | |
Customization
Toolbar
renderTopToolbar: ({ table }) => ( <Box sx={{ display: 'flex', gap: 2, p: 2 }}> <MRT_GlobalFilterTextField table={table} /> <ExportButton data={data} /> </Box> ),
Row Styling
muiTableBodyRowProps: ({ row }) => ({ sx: { backgroundColor: row.original.isHighlighted ? 'action.hover' : undefined }, }),
Localization
import { MRT_Localization_ES } from 'material-react-table/locales/es'; localization: MRT_Localization_ES,
Filter Variants
| Type | Variant | Use Case |
|---|---|---|
| Text | (default) | Free text search |
| Select | | Enum/status fields |
| Multi-select | | Tags, categories |
| Range | | Numeric ranges |
| Range Slider | | Price, age |
| Date | | Date fields |
| Date Range | | Date ranges |
| Autocomplete | | Large option sets |
| Checkbox | | Boolean fields |
React Query Integration
function UsersTable() { const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>([]); const [globalFilter, setGlobalFilter] = useState(''); const [sorting, setSorting] = useState<MRT_SortingState>([]); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); const { data, isLoading, isError } = useQuery({ queryKey: ['users', columnFilters, globalFilter, pagination, sorting], queryFn: () => fetchUsers({ columnFilters, globalFilter, pagination, sorting }), placeholderData: keepPreviousData, }); const table = useMaterialReactTable({ columns, data: data?.users ?? [], rowCount: data?.meta?.totalRowCount ?? 0, manualFiltering: true, manualPagination: true, manualSorting: true, state: { columnFilters, globalFilter, isLoading, pagination, showAlertBanner: isError, sorting }, onColumnFiltersChange: setColumnFilters, onGlobalFilterChange: setGlobalFilter, onPaginationChange: setPagination, onSortingChange: setSorting, }); return <MaterialReactTable table={table} />; }
Anti-Patterns
| Don't | Do |
|---|---|
| Recreate columns on every render | Wrap in |
| Fetch all data for server-side | Implement backend pagination |
| Skip virtualization for 10k+ rows | Enable |
| Custom filter UI for common cases | Use built-in |
| Ignore loading states | Use state prop |
| Inline column definitions | Define outside component or |
| Hardcode table text | Use prop |
Dependencies
npm install material-react-table @mui/material @mui/x-date-pickers @mui/icons-material @emotion/react @emotion/styled @tanstack/react-query
Version Compatibility
| MRT | MUI | React | Notes |
|---|---|---|---|
| V3 | 6+ (v7 experimental) | 18+ | Current - keyboard nav default |
| V2 | 5.11+ | 17+ | Maintenance |
| V1 | 5.0+ | 17+ | Deprecated |
MUI v7 Status: ⚠️ Not officially supported yet. Known issues: dark mode broken, TypeScript errors. Use
--legacy-peer-deps if required. Track GitHub #1401.
Key V2→V3 changes:
text → label in select options, keyboard nav enabled by default.
Checklist
- Columns wrapped in
useMemo - Proper accessors (
|accessorKey
+accessorFn
)id -
set per column typefilterVariant - Server-side for > 100 rows
- Virtualization for > 10k rows
-
state connectedisLoading - Error states handled (
)showAlertBanner - Validation in
onEditingRowSave - Row actions labeled for a11y
-
if using date filtersLocalizationProvider - Version-appropriate props (V1→V2→V3 renames)
- z-index handled if table in modal/drawer