Migration from v4 to v5
This guide describes the changes needed to migrate the Data Grid from v4 to v5.
Introduction
This is a reference guide for upgrading your site from MUI X v4 to v5. MUI X v5 is fully compatible with Material UI v5 and MUI System v5 and can be used with Material UI v4 and MUI System v4 with some additional steps. Most breaking changes are renaming of CSS classes or variables to improve the consistency of the Data Grid.
Migrating MUI Core from v4
Using MUI Core v4 with v5
Using Material UI v4 with v5 can be achieved with the following steps:
- First, make sure you have Material UI v5 installed. If not, install it with these instructions.
- Add a custom
createGenerateClassNameto disable the generation of global class names in JSS.
import { createGenerateClassName } from '@material-ui/core/styles';
const generateClassName = createGenerateClassName({
// By enabling this option, if you have non-MUI elements (for example `<div />`)
// using MUI classes (for example `.MuiButton`) they will lose styles.
// Make sure to convert them to use `styled()` or `<Box />` first.
disableGlobal: true,
// Class names will receive this seed to avoid name collisions.
seed: 'mui-jss',
});
- Create a v5 theme with the same customizations as the v4 theme. This has to be done as the theme is not shared between different Material UI versions.
import { createMuiTheme as createThemeV4 } from '@material-ui/core/styles';
import { createTheme as createThemeV5 } from '@mui/material/styles';
const themeV4 = createThemeV4({
palette: {
primary: {
main: '#2196f3',
},
},
});
const themeV5 = createThemeV5({
palette: {
primary: {
main: themeV4.palette.primary.main,
},
},
});
- Apply the class name generator and v5 theme to the application.
import * as React from 'react';
import { ThemeProvider as ThemeProviderV5 } from '@mui/material/styles';
import { ThemeProvider as ThemeProviderV4, StylesProvider } from '@material-ui/core/styles';
const generateClassName = createGenerateClassName({ ... });
const themeV4 = createThemeV4({ ... });
const themeV5 = createThemeV5({ ... });
export default function DataGridDemo() {
return (
<StylesProvider generateClassName={generateClassName}>
<ThemeProviderV4 theme={themeV4}>
<ThemeProviderV5 theme={themeV5}>
{/* Your component tree. */}
</ThemeProviderV5>
</ThemeProviderV4>
</StylesProvider>
);
}
Done! Now, you can render any dependencies that rely on Material UI v5 without upgrading from v4, and they will both run seamlessly alongside. For example, the following interactive demo shows how these steps tie together with the Data Grid:
Migrating MUI X
Update MUI X version
To use the v5 version of MUI X, you first need to update to the new package names:
@material-ui/data-gridis now@mui/x-data-grid(MIT)@material-ui/x-gridis now@mui/x-data-grid-pro(Commercial)
CSS classes
Some CSS classes were removed or renamed
MUI X v4 classes MUI X v5 classes .MuiDataGrid-windowremoved .MuiDataGrid-windowContainerremoved .MuiDataGrid-viewport.MuiDataGrid-virtualScroller.MuiDataGrid-dataContainer.MuiDataGrid-virtualScrollerContent.MuiDataGrid-renderingZone.MuiDataGrid-virtualScrollerRenderZone.MuiDataGrid-gridMenuList.MuiDataGrid-menuList.MuiGridToolbarContainer-root.MuiDataGrid-toolbarContainer.MuiGridMenu-root.MuiDataGrid-menu.MuiDataGridColumnsPanel-root.MuiDataGrid-columnsPanel.MuiGridPanel-root.MuiDataGrid-panel.MuiGridPanelContent-root.MuiDataGrid-panelContent.MuiGridPanelFooter-root.MuiDataGrid-panelFooter.MuiDataGridPanelHeader-root.MuiDataGrid-panelHeader.MuiGridPanelWrapper-root.MuiDataGrid-panelWrapper.MuiGridFilterForm-root.MuiDataGrid-filterForm.MuiGridToolbarFilterButton-root.MuiDataGrid-toolbarFilterList
Module augmentation
The module augmentation is no longer enabled by default. This change was done to prevent conflicts with projects using Data Grid and Data Grid Pro together.
In order to still be able to do overrides at the theme level, add the following imports to your project:
+import type {} from '@mui/x-data-grid/themeAugmentation'; +import type {} from '@mui/x-data-grid-pro/themeAugmentation';
Virtualization
The
onViewportRowsChangeprop and theviewportRowsChangeevent have been removedYou can replace them with a listener on the
rowsScrollevent:const apiRef = useGridApiRef(); const prevRenderContext = React.useRef(null); React.useEffect(() => { return apiRef.current.subscribeEvent('rowsScroll', ({ renderContext }) => { if ( !prevRenderContext.current || renderContext.firstRowIdx !== prevRenderContext.current.firstRowIndex || renderContext.lastRowIdx !== prevRenderContext.current.lastRowIndex ) { prevRenderContext.current = renderContext; const params = { firstRowIndex: renderContext.firstRowIndex, lastRowIndex: renderContext.lastRowIndex, }; } }); }, [apiRef]); <DataGridPro apiRef={apiRef} />;
Removed props
Some event listeners and DOM attributes were removed from
GridCellandGridRowto improve performance.The following props were removed.
onCellBluronCellOveronCellOutonCellEnteronCellLeaveonRowOveronRowOutonRowEnteronRowLeave
If you depend on them, you can use
componentsProps.rowandcomponentsProps.cellto pass custom props to the row or cell. For more information, check this page. Example:-<DataGrid onRowOver={handleRowOver} />; +<DataGrid + componentsProps={{ + row: { onMouseOver: handleRowOver }, + }} +/>;The
data-rowindexanddata-rowselectedattributes were removed from the cell element. Equivalent attributes can be found in the row element.The
data-editableattribute was removed from the cell element. Use the.MuiDataGrid-cell--editableCSS class.The
data-modeattribute was removed from the cell element. Use the.MuiDataGrid-cell--editingCSS class.
State access
The state direct access is not considered part of the public API anymore. We only guarantee that the selectors continue to work between minor releases. We advise you to avoid accessing directly a state sub-key, instead use the available selectors or
apiRefmethods whenever possible. You can replace the following state access by their matching selectors:Direct state access Selector state.rowsgridRowsStateSelectorstate.filtergridFilterStateSelectorstate.sortinggridSortingStateSelectorstate.editRowsgridEditRowsStateSelectorstate.paginationgridPaginationSelectorstate.columnsgridColumnsSelectorstate.columnMenugridColumnMenuSelectorstate.focusgridFocusStateSelectorstate.tabIndexgridTabIndexStateSelectorstate.selectiongridSelectionStateSelectorstate.preferencePanelgridPreferencePanelStateSelectorstate.densitygridDensitySelectorstate.columnReordergridColumnReorderSelectorstate.columnResizegridColumnResizeSelectorThe
apiRef.current.getStatemethod was removed. You can directly access the state throughapiRef.current.state-const state = apiRef.current.getState(); +const state = apiRef.current.state const filterModel = gridFilterModelSelector(state);The
stateprop was not working correctly and was removed. You can use the newinitialStateprop instead.Note that
initialStateonly allows thepreferencePanel,filter.filterModelandsort.sortModelkeys. To fully control the state, use the feature's model prop and change callback (for examplefilterModelandonFilterModelChange).<DataGrid - state={{ + initialState={{ preferencePanel: { open: true, openedPanelValue: GridPreferencePanelsValue.filters, }, }} />Some selectors have been renamed to match with our naming convention:
MUI X v4 selectors MUI X v5 selectors unorderedGridRowIdsSelectorgridRowIdsSelectorsortingGridStateSelectorgridSortingStateSelectorsortedGridRowIdsSelectorgridSortedRowIdsSelectorfilterGridStateSelectorgridFilterModelSelectorvisibleSortedGridRowIdsSelectorgridVisibleSortedRowIdsSelectorvisibleGridRowCountSelectorgridVisibleRowCountSelectorfilterGridColumnLookupSelectorgridFilterActiveItemsLookupSelectordensitySelectorgridDensitySelectorSome selectors have been removed/reworked
sortedGridRowsSelectorwas removed. You can usegridSortedRowEntriesSelectorinstead.
The return format has changed:
-sortedGridRowsSelector: (state: GridState) => Map<GridRowId, GridRowModel> +gridSortedRowEntriesSelector: (state: GridState) => GridRowEntry[]If you need the old format, you can convert the selector return value as follows:
-const map = sortedGridRowsSelector(state); +const map = new Map(gridSortedRowEntriesSelector(state).map(row => [row.id, row.model]));filterGridItemsCounterSelectorwas removed. You can usegridFilterActiveItemsSelector
-const filterCount = filterGridItemsCounterSelector(state); +const filterCount = gridFilterActiveItemsSelector(state).length;unorderedGridRowModelsSelectorwas removed. You can useapiRef.current.getRowModelsorgridRowIdsSelectorandgridRowsLookupSelector
-const rowModels = unorderedGridRowModelsSelector(apiRef.current.state); // using the `apiRef` +const rowModels = apiRef.current.getRowModels(); // using selectors +const allRows = gridRowIdsSelector(apiRef.current.state); +const idRowsLookup = gridRowsLookupSelector(apiRef.current.state); +const rowModels = new Map(allRows.map((id) => [id, idRowsLookup[id]]));- The
visibleSortedGridRowsSelectorwas removed. You can usegridVisibleSortedRowEntriesSelector
The return format has changed:
-visibleSortedGridRowsSelector: (state: GridState) => Map<GridRowId, GridRowModel>; +gridVisibleSortedRowEntriesSelector: (state: GridState) => GridRowEntry[];If you need the old format, you can convert the selector return value as follows:
-const map = visibleSortedGridRowsSelector(state); +const map = new Map(gridVisibleSortedRowEntriesSelector(state).map(row => [row.id, row.model]));- The
visibleSortedGridRowsAsArraySelectorwas removed. You can usegridVisibleSortedRowEntriesSelector
The return format has changed:
-visibleSortedGridRowsAsArraySelector: (state: GridState) => [GridRowId, GridRowData][]; +gridVisibleSortedRowEntriesSelector: (state: GridState) => GridRowEntry[];If you need the old format, you can convert the selector return value as follows:
-const rows = visibleSortedGridRowsAsArraySelector(state); +const rows = gridVisibleSortedRowEntriesSelector(state).map(row => [row.id, row.model]);
apiRef methods
The
apiRefmethods to partially update the filter model have been renamed:apiRef.current.applyFilterLinkOperatorwas renamed toapiRef.current.setFilterLinkOperatorapiRef.current.upsertFilterwas renamed toapiRef.current.upsertFilterItemapiRef.current.deleteFilterwas renamed toapiRef.current.deleteFilterItem
The third argument in
apiRef.current.selectRowis now inverted to keep consistency with other selection APIs.If you were passing
allowMultiple: true, you should now passresetSelection: falseor stop passing anything.If you were passing
allowMultiple: falseor not passing anything onallowMultiple, you should now passresetSelection: true.-selectRow: (id: GridRowId, isSelected?: boolean, allowMultiple?: boolean = false) => void; +selectRow: (id: GridRowId, isSelected?: boolean, resetSelection?: boolean = false) => void;
Columns
The params passed to the
valueFormatterwere changed.You can use the
apito get the missing params. TheGridValueFormatterParamsinterface has the following signature now:-export type GridValueFormatterParams = Omit<GridRenderCellParams, 'formattedValue' | 'isEditable'>; +export interface GridValueFormatterParams { + /** + * The column field of the cell that triggered the event. + */ + field: string; + /** + * The cell value, but if the column has valueGetter, use getValue. + */ + value: GridCellValue; + /** + * GridApi that lets you manipulate the Data Grid. + */ + api: any; +}
Other exports
The
gridCheckboxSelectionColDefwas renamed toGRID_CHECKBOX_SELECTION_COL_DEF.The individual string constants have been removed in favor of a single
gridClassesobject-const columnHeaderClass = GRID_COLUMN_HEADER_CSS_CLASS; +const columnHeaderClass = gridClasses.columnHeader; -const rowClass = GRID_ROW_CSS_CLASS; +const rowClass = gridClasses.row; -const cellClass = GRID_CELL_CSS_CLASS; +const cellClass = gridClasses.cell; -const columnSeparatorClass = GRID_COLUMN_HEADER_SEPARATOR_RESIZABLE_CSS_CLASS; +const columnSeparatorClass = gridClasses['columnSeparator--resizable']; -const columnHeaderTitleClass = GRID_COLUMN_HEADER_TITLE_CSS_CLASS; +const columnHeaderTitleClass = gridClasses.columnHeaderTitle; -const columnHeaderDropZoneClass = GRID_COLUMN_HEADER_DROP_ZONE_CSS_CLASS; +const columnHeaderDropZoneClass = gridClasses.columnHeaderDropZone; -const columnHeaderDraggingClass = GRID_COLUMN_HEADER_DRAGGING_CSS_CLASS; +const columnHeaderDraggingClass = gridClasses['columnHeader--dragging'];The constants referring to the column types were removed. Their values can be hardcoded.
-const isColumnString = column.type === GRID_STRING_COLUMN_TYPE; +const isColumnString = col.type === 'string'; -const isColumnNumber = col.type === GRID_NUMBER_COLUMN_TYPE; +const isColumnNumber = col.type === 'number'; -const isColumnDate = col.type === GRID_DATE_COLUMN_TYPE; +const isColumnDate = col.type === 'date'; -const isColumnDateTime = col.type === GRID_DATETIME_COLUMN_TYPE; +const isColumnDateTime = col.type === 'dateTime'; -const isColumnBoolean = col.type === GRID_BOOLEAN_COLUMN_TYPE; +const isColumnBoolean = col.type === 'boolean';The hook
useGridSlotComponentPropswas removed. You can use the following hooks to access the same data.-const { apiRef, state, rootElement, options } = useGridSlotComponentProps(); +const apiRef = useGridApiContext(); +const [state] = useGridState(apiRef); +const rootElement = apiRef.current.rootElementRef; +const rootProps = useGridRootProps(); // equivalent of `options`
Removals from the public API
We removed some API methods/selectors from what we consider public by adding the unstable_ prefix on them.
You can continue to use these methods if you desire, but they may be subject to breaking changes in the future without prior notice.
apiRef.current.applyFilterswas renamedapiRef.current.unstable_applyFiltersgridContainerSizesSelectorwas renamedunstable_gridContainerSizesSelectorgridViewportSizesSelectorwas renamedunstable_gridViewportSizesSelectorgridScrollBarSizeSelectorwas renamedunstable_gridScrollBarSizeSelector