The Material-UI Data Grid is easily the largest and most customizable component in the MUI library. It has more subcomponents and props than any other component. In this tutorial I will review common features of the Data Grid: sorting, filtering, exporting, pagination, and cell editing.
I will also review the docs and some challenges I had with the Data Grid. Frustratingly, their were either bugs in the Data Grid or some props are so difficult to understand that I couldn’t tell the difference. The component has so much promise, but I think people will find attempts to go beyond default options too difficult.
Finally, an important consideration to remember with the Data Grid is that many props get set at the column level, while other props get set at the Data Grid level. For example, disabling sorting on a column requires a column prop, but setting a default sort on a column requires a Data Grid prop. We’ll see this in the code later on.
Full code with TypeScript for this Data Grid tutorial can be found in the Resources section.
YouTube video is here or watch below:
MUI Data Grid Sorting
The Data Grid has sorting enabled by default. If you don’t want a particular column to sort, disable it by setting sortable: false
on the column.
Here’s how the sort looks in the Data Grid header. Notice the arrow icon as a shortcut.

You can also set a default sort that takes effect on initial load of the component. Use the initialState prop at the Data Grid level. In this case I have set my field column to have an ascending sort on load.
initialState={{
sorting: { sortModel: [{ field: "state", sort: "asc" }] }
}}
Custom sort algorithms can be set using the sortComparator
prop at the column level. This would simply compare the two values in a unique way that fits your requirements.
MUI Data Grid Filtering
Filtering is also enabled by default. You can see it in the screenshot alongside sort functionality in the previous section.
Filtering can be disabled at the column level with filterable: false
. It can be disabled for all columns by passing disableColumnFilter
to the DataGrid.
I also attempted to set initialState.filter.filterModel
on the Data Grid to set a default filter for the zip code column. I passed the required params of columnField
, operatorValue
, and value
. However, the Data Grid threw an error:

The following are potential reasons for this issue:
- I misunderstood the docs
- This feature has a bug
- I am attempting an invalid operator for a string field
Regardless, it was disappointing that after spending a reasonable amount of time digging into examples, I still couldn’t get the default filter to work.
MUI Data Grid Exporting
Exporting contents of the Data Grid can be enabled by passing a GridToolbar to the Data Grid:
components={{Toolbar: GridToolbar}}
This enables cool features like column hiding as well. However, this duplicates the filter option (it’s also available on each column).

I recommend passing a more precise value that contains only the Toolbar options you intend to use:
components={{ Toolbar: () => {
return (<GridToolbarContainer sx={{justifyContent: 'flex-end'}}>
<GridToolbarExport />
</GridToolbarContainer>)}
}}
Here I’ve passed a GridToolbarContainer that only has an export option. I also right-aligned the export.
If you don’t want a particular column exported, add disableExport: true
to the column.
MUI Data Grid Pagination
Pagination was one of the simpler features to experiment with. There are two primary ways to configure pagination:
- Auto-detect grid height and render few enough rows so a scrollbar isn’t needed.
- Configure page size options that will render a set amount of rows regardless of grid height. This is the default.
Here’s an example of rendering based on grid height. This required setting autoPageSize={true}
at the Data Grid level. Notice there is no “Rows per page” dropdown.

Here’s what the default pagination configuration looks like, except that I’ve configured the rows per page to have options of 20, 50, and 100.

Here’s more ideas for customizing the pagination component.
MUI Data Grid Cell Editing
Data Grid cells are not editable by default. However, editing can be enabled with editable: true
at the column level.
Surprisingly, there are lots of configurations for editing. They primarily involve handling edit change events and controlling what the data looks like while editing.
I attempted to customize the rendered text during editing:

I used the following prop at the cell level:
renderEditCell: (val) => {console.log(val.value); return `Editing: ${val.value}` }
However, this didn’t take into account the changes to value and thus rendered the cell uneditable. I was attempting a simplified version of this example from the MUI docs. I found it complex to the point of being inaccessible. I only have access to the free Data Grid version, not the pro version, and perhaps if I had support from the MUI team then this feature would not be so challenging.
Material-UI Data Grid Bugs?
I’ve written almost 100 MUI articles on this site. I have encountered occasional head-scratchers and “is that a bug?” moments. However, I have found very specific problems with the Data Grid that I think are worth highlighting below. I still think the Data Grid is an excellent component, but be careful about customizing the "@mui/x-data-grid"
version (or using it with TypeScript).
TypeScript challenges:
- I tried to type my rows as type
GridRowsProp
from@mui/x-data-grid
. However, this was set to a readonly array and thus lacked the push function. I ended up retyping the rows const. - I had to set
//@ts-ignore
on myGridToolbarContainer
in order to use sx props with it. The sx prop obviously works, but MUI seems to be lacking proper typing for it on this component. - Pagination is enabled by default. In fact, it can’t be disabled if you are using TypeScript. The
pagination
prop typing only allowstrue
orundefined
as values. Maybe this is intentional, but then why include the prop?
Code challenges:
- Data Grid
height
vs.minHeight
. This was a difficult one…I initially setminHeight
on the Data Grid instead ofheight
. I couldn’t figure out why the rows wouldn’t render! It turns out that the Data Grid seems to not be unable to set height usingminHeight
. My guess is a fixed height is required for internal calculations such asautoPageSize
. - Various challenges with getting customizations to work (renderEditCell, filterModel, and so on). Maybe this is MUI’s fault, maybe this is my fault.

Resources
Here’s a deep dive into customizing Data Grid styling and using renderCell.
Here’s how to add components to Data Grid columns.
I experimented with expandable rows in the free DataGrid, and it went better than expected!
import * as React from "react";
import { Paper, SxProps } from "@mui/material";
import { DataGrid, GridToolbar, GridRowsProp, GridColDef, GridToolbarContainer, GridToolbarExport } from "@mui/x-data-grid";
import { faker } from "@faker-js/faker";
const columns: GridColDef[] = [
{
field: "address",
headerName: "Street/Appt Address",
flex: 2,
sortable: false,
disableExport: true,
filterable: false,
editable: true
},
{ field: "zip", headerName: "Zip Code", flex: 1, /*sortComparator: {}*/ },
{ field: "city", headerName: "City", flex: 1 },
{ field: "state", headerName: "State", flex: 1, editable: true, /* renderEditCell: (val) => {console.log(val.value); return `Editing: ${val.value}` } */},
];
//const addresses: GridRowsProp = [];
const addresses: {
[key: string]: any;
}[] = [];
for (let i = 0; i < 200; i++) {
addresses.push({
id: i+1,
address: `${faker.address.streetAddress()} ${faker.address.secondaryAddress()}`,
zip: faker.address.zipCode(),
city: faker.address.city(),
state: faker.address.state(),
});
}
const datagridSx: SxProps = {
marginLeft: "auto",
marginRight: "auto",
marginTop: 4,
width: "100%",
//minHeight: 500,
height: 500,
borderRadius: 2,
};
export default function TutorialDataGrid() {
//const [pageSize, setPageSize] = React.useState(20);
return (
<Paper sx={datagridSx}>
<DataGrid
rows={addresses}
columns={columns}
//@ts-ignore
components={{ Toolbar: () => {return (<GridToolbarContainer sx={{justifyContent: 'flex-end'}}>
<GridToolbarExport />
</GridToolbarContainer>)} }}
initialState={{
sorting: { sortModel: [{ field: "state", sort: "asc" }] },
// filter: {
// filterModel: {
// items: [
// {
// columnField: 'zip',
// operatorValue: '=',
// value: '78701'
// },
// ],
// },
// }
}}
pagination={undefined}
//autoPageSize={true}
// pageSize={pageSize}
// onPageSizeChange={(newPageSize) => setPageSize(newPageSize)}
// rowsPerPageOptions={[20, 50, 100]}
/>
</Paper>
);
}
Hi Jon,
Nice post. I am unable to get the ‘sx’ working on the GridToolbarContainer. What version of x-data-grid did you use?
Thanks!
Hi Lynnae, I’m using @mui/x-data-grid 5.6.1. I had the same problem occur when I made the YouTube version of this post. It worked…until it didn’t. I finally had to use the style prop. I suspect a bug was introduced in a patch version of x-data-grid.
Alternatively, you can add @ts-ignore in the line above the GridToolbarContainer.
Hi – Nice Post – wrt to the filtering options not working… I got it working as follow:
const [filterModel, setFilterModel] = React.useState({
items: [
{
columnField: ‘movementType’,
operatorValue: ‘equals’, // This should be text check current available values in dropdown when setting filter manually.
value: movementTypeToggle,
},
],
});
Hi Jon,
your tutorial is very good, to make it better I could put drag and drop columns and search =)
I am learning nextjs. Wanted to create datagrid with mui for crud management.
This is ok with simulated data and client side process for limited data.
How do you do filter with mysql database with sort filter search etc.
You can update tutorial with mysql as data providers and server side filter / search etc.