Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Avoid <GridRoot /> double-render pass on mount in SPA mode (@lauri865) #16480

Merged
merged 5 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/data/data-grid/events/events.json
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,13 @@
"params": "ElementSize",
"event": "MuiEvent<{}>"
},
{
"projects": ["x-data-grid", "x-data-grid-pro", "x-data-grid-premium"],
"name": "rootMount",
"description": "Fired when rootElementRef.current becomes available.",
"params": "HTMLElement",
"event": "MuiEvent<{}>"
},
{
"projects": ["x-data-grid", "x-data-grid-pro", "x-data-grid-premium"],
"name": "rowClick",
Expand Down
12 changes: 8 additions & 4 deletions docs/data/data-grid/filtering-recipes/FilteredRowCount.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ export default function FilteredRowCount() {

const getFilteredRowsCount = React.useCallback(
(filterModel) => {
const { filteredRowsLookup } = apiRef.current.getFilterState(filterModel);
return Object.keys(filteredRowsLookup).filter(
(rowId) => filteredRowsLookup[rowId] === true,
).length;
const rowIds = apiRef.current?.getAllRowIds();
const filterState = apiRef.current?.getFilterState(filterModel);
if (!rowIds || !filterState) {
return 0;
}

const { filteredRowsLookup } = filterState;
return rowIds.filter((rowId) => filteredRowsLookup[rowId] !== false).length;
},
[apiRef],
);
Expand Down
12 changes: 8 additions & 4 deletions docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ export default function FilteredRowCount() {

const getFilteredRowsCount = React.useCallback(
(filterModel: GridFilterModel) => {
const { filteredRowsLookup } = apiRef.current.getFilterState(filterModel);
return Object.keys(filteredRowsLookup).filter(
(rowId) => filteredRowsLookup[rowId] === true,
).length;
const rowIds = apiRef.current?.getAllRowIds();
const filterState = apiRef.current?.getFilterState(filterModel);
if (!rowIds || !filterState) {
return 0;
}

const { filteredRowsLookup } = filterState;
return rowIds.filter((rowId) => filteredRowsLookup[rowId] !== false).length;
},
[apiRef],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const configuration = {
},
};
const releaseInfo = getReleaseInfo();
const watermark = <Watermark packageName="x-data-grid-premium" releaseInfo={releaseInfo} />;

let dataGridPremiumPropValidators: PropValidator<DataGridPremiumProcessedProps>[];

Expand All @@ -47,6 +48,7 @@ const DataGridPremiumRaw = forwardRef(function DataGridPremium<R extends GridVal
if (process.env.NODE_ENV !== 'production') {
validateProps(props, dataGridPremiumPropValidators);
}

return (
<GridContextProvider privateApiRef={privateApiRef} configuration={configuration} props={props}>
<GridRoot
Expand All @@ -57,7 +59,7 @@ const DataGridPremiumRaw = forwardRef(function DataGridPremium<R extends GridVal
{...props.slotProps?.root}
ref={ref}
>
<Watermark packageName="x-data-grid-premium" releaseInfo={releaseInfo} />
{watermark}
</GridRoot>
</GridContextProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ export const useDataGridPremiumComponent = (
/**
* Register all state initializers here.
*/
useGridInitializeState(dimensionsStateInitializer, apiRef, props);
useGridInitializeState(headerFilteringStateInitializer, apiRef, props);
useGridInitializeState(rowGroupingStateInitializer, apiRef, props);
useGridInitializeState(aggregationStateInitializer, apiRef, props);
Expand All @@ -142,11 +141,12 @@ export const useDataGridPremiumComponent = (
useGridInitializeState(densityStateInitializer, apiRef, props);
useGridInitializeState(columnReorderStateInitializer, apiRef, props);
useGridInitializeState(columnResizeStateInitializer, apiRef, props);
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(columnMenuStateInitializer, apiRef, props);
useGridInitializeState(columnGroupsStateInitializer, apiRef, props);
useGridInitializeState(virtualizationStateInitializer, apiRef, props);
useGridInitializeState(dataSourceStateInitializer, apiRef, props);
useGridInitializeState(dimensionsStateInitializer, apiRef, props);
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(listViewStateInitializer, apiRef, props);

useGridRowGrouping(apiRef, props);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export const useGridAggregation = (
const currentModel = gridAggregationModelSelector(apiRef);
if (currentModel !== model) {
apiRef.current.setState(mergeStateWithAggregationModel(model));
apiRef.current.forceUpdate();
}
},
[apiRef],
Expand Down Expand Up @@ -118,7 +117,6 @@ export const useGridAggregation = (

// Re-apply the column hydration to wrap / unwrap the aggregated columns
if (!areAggregationRulesEqual(rulesOnLastColumnHydration, aggregationRules)) {
apiRef.current.caches.aggregation.rulesOnLastColumnHydration = aggregationRules;
apiRef.current.requestPipeProcessorsApplication('hydrateColumns');
}
}, [apiRef, applyAggregation, props.aggregationFunctions, props.disableAggregation]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ export const useGridAggregationPreProcessors = (
});

rulesOnLastColumnHydration.current = aggregationRules;

apiRef.current.caches.aggregation.rulesOnLastColumnHydration = aggregationRules;

return columnsState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
isNavigationKey,
serializeCellValue,
useGridRegisterPipeProcessor,
useGridVisibleRows,
} from '@mui/x-data-grid-pro/internals';
import {
useGridApiEventHandler,
Expand All @@ -26,7 +25,6 @@ import {
gridFocusCellSelector,
GridCellParams,
GRID_REORDER_COL_DEF,
useGridSelector,
gridSortedRowIdsSelector,
gridDimensionsSelector,
} from '@mui/x-data-grid-pro';
Expand Down Expand Up @@ -64,13 +62,10 @@ export const useGridCellSelection = (
>,
) => {
const hasRootReference = apiRef.current.rootElementRef.current !== null;
const visibleRows = useGridVisibleRows(apiRef, props);
const cellWithVirtualFocus = React.useRef<GridCellCoordinates>(null);
const lastMouseDownCell = React.useRef<GridCellCoordinates>(null);
const mousePosition = React.useRef<{ x: number; y: number }>(null);
const autoScrollRAF = React.useRef<number>(null);
const sortedRowIds = useGridSelector(apiRef, gridSortedRowIdsSelector);
const dimensions = useGridSelector(apiRef, gridDimensionsSelector);
const totalHeaderHeight = getTotalHeaderHeight(apiRef, props);

const ignoreValueFormatterProp = props.ignoreValueFormatterDuringExport;
Expand Down Expand Up @@ -145,6 +140,7 @@ export const useGridCellSelection = (
}

const visibleColumns = apiRef.current.getVisibleColumns();
const visibleRows = getVisibleRows(apiRef);
const rowsInRange = visibleRows.rows.slice(finalStartRowIndex, finalEndRowIndex + 1);
const columnsInRange = visibleColumns.slice(finalStartColumnIndex, finalEndColumnIndex + 1);

Expand All @@ -161,7 +157,7 @@ export const useGridCellSelection = (

apiRef.current.setCellSelectionModel(newModel);
},
[apiRef, visibleRows.rows],
[apiRef],
);

const getSelectedCellsAsArray = React.useCallback<
Expand Down Expand Up @@ -293,6 +289,8 @@ export const useGridCellSelection = (
return;
}

const dimensions = gridDimensionsSelector(apiRef.current.state);

const { x: mouseX, y: mouseY } = mousePosition.current;
const { width, height: viewportOuterHeight } = dimensions.viewportOuterSize;
const height = viewportOuterHeight - totalHeaderHeight;
Expand Down Expand Up @@ -332,7 +330,7 @@ export const useGridCellSelection = (
}

autoScroll();
}, [apiRef, dimensions, totalHeaderHeight]);
}, [apiRef, totalHeaderHeight]);

const handleCellMouseOver = React.useCallback<GridEventListener<'cellMouseOver'>>(
(params, event) => {
Expand All @@ -355,6 +353,7 @@ export const useGridCellSelection = (
return;
}

const dimensions = gridDimensionsSelector(apiRef.current.state);
const { x, y } = virtualScrollerRect;
const { width, height: viewportOuterHeight } = dimensions.viewportOuterSize;
const height = viewportOuterHeight - totalHeaderHeight;
Expand All @@ -379,7 +378,7 @@ export const useGridCellSelection = (
stopAutoScroll();
}
},
[apiRef, startAutoScroll, stopAutoScroll, totalHeaderHeight, dimensions],
[apiRef, startAutoScroll, stopAutoScroll, totalHeaderHeight],
);

const handleCellClick = useEventCallback<
Expand Down Expand Up @@ -439,6 +438,7 @@ export const useGridCellSelection = (
endColumnIndex -= 1;
}

const visibleRows = getVisibleRows(apiRef);
if (endRowIndex < 0 || endRowIndex >= visibleRows.rows.length) {
return;
}
Expand Down Expand Up @@ -491,6 +491,7 @@ export const useGridCellSelection = (

const addClassesToCells = React.useCallback<GridPipeProcessor<'cellClassName'>>(
(classes, { id, field }) => {
const visibleRows = getVisibleRows(apiRef);
if (!visibleRows.range || !apiRef.current.isCellSelected(id, field)) {
return classes;
}
Expand Down Expand Up @@ -539,7 +540,7 @@ export const useGridCellSelection = (

return newClasses;
},
[apiRef, visibleRows.range, visibleRows.rows],
[apiRef],
);

const canUpdateFocus = React.useCallback<GridPipeProcessor<'canUpdateFocus'>>(
Expand Down Expand Up @@ -567,6 +568,7 @@ export const useGridCellSelection = (
if (apiRef.current.getSelectedCellsAsArray().length <= 1) {
return value;
}
const sortedRowIds = gridSortedRowIdsSelector(apiRef);
const cellSelectionModel = apiRef.current.getCellSelectionModel();
const unsortedSelectedRowIds = Object.keys(cellSelectionModel);
const sortedSelectedRowIds = sortedRowIds.filter((id) =>
Expand Down Expand Up @@ -595,7 +597,7 @@ export const useGridCellSelection = (
}, '');
return copyData;
},
[apiRef, ignoreValueFormatter, clipboardCopyCellDelimiter, sortedRowIds],
[apiRef, ignoreValueFormatter, clipboardCopyCellDelimiter],
);

useGridRegisterPipeProcessor(apiRef, 'isCellSelected', checkIfCellIsSelected);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { RefObject } from '@mui/x-internals/types';
import {
GridRowId,
GridRowTreeConfig,
GridFilterState,
GridFilterModel,
Expand Down Expand Up @@ -79,9 +78,9 @@ export const filterRowTreeFromGroupingColumns = (
params: FilterRowTreeFromTreeDataParams,
): Omit<GridFilterState, 'filterModel'> => {
const { apiRef, rowTree, isRowMatchingFilters, filterModel } = params;
const filteredRowsLookup: Record<GridRowId, boolean> = {};
const filteredChildrenCountLookup: Record<GridRowId, number> = {};
const filteredDescendantCountLookup: Record<GridRowId, number> = {};
const filteredRowsLookup: GridFilterState['filteredRowsLookup'] = {};
const filteredChildrenCountLookup: GridFilterState['filteredChildrenCountLookup'] = {};
const filteredDescendantCountLookup: GridFilterState['filteredDescendantCountLookup'] = {};
const filterCache = {};

const filterTreeNode = (
Expand Down
4 changes: 3 additions & 1 deletion packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const configuration = {
},
};
const releaseInfo = getReleaseInfo();
const watermark = <Watermark packageName="x-data-grid-pro" releaseInfo={releaseInfo} />;

const DataGridProRaw = forwardRef(function DataGridPro<R extends GridValidRowModel>(
inProps: DataGridProProps<R>,
Expand All @@ -34,6 +35,7 @@ const DataGridProRaw = forwardRef(function DataGridPro<R extends GridValidRowMod
if (process.env.NODE_ENV !== 'production') {
validateProps(props, propValidatorsDataGridPro);
}

return (
<GridContextProvider privateApiRef={privateApiRef} configuration={configuration} props={props}>
<GridRoot
Expand All @@ -44,7 +46,7 @@ const DataGridProRaw = forwardRef(function DataGridPro<R extends GridValidRowMod
{...props.slotProps?.root}
ref={ref}
>
<Watermark packageName="x-data-grid-pro" releaseInfo={releaseInfo} />
{watermark}
</GridRoot>
</GridContextProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ export const useDataGridProComponent = (
/**
* Register all state initializers here.
*/
useGridInitializeState(dimensionsStateInitializer, apiRef, props);
useGridInitializeState(headerFilteringStateInitializer, apiRef, props);
useGridInitializeState(rowSelectionStateInitializer, apiRef, props);
useGridInitializeState(detailPanelStateInitializer, apiRef, props);
Expand All @@ -129,11 +128,12 @@ export const useDataGridProComponent = (
useGridInitializeState(densityStateInitializer, apiRef, props);
useGridInitializeState(columnReorderStateInitializer, apiRef, props);
useGridInitializeState(columnResizeStateInitializer, apiRef, props);
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(columnMenuStateInitializer, apiRef, props);
useGridInitializeState(columnGroupsStateInitializer, apiRef, props);
useGridInitializeState(virtualizationStateInitializer, apiRef, props);
useGridInitializeState(dataSourceStateInitializer, apiRef, props);
useGridInitializeState(dimensionsStateInitializer, apiRef, props);
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(listViewStateInitializer, apiRef, props);

useGridHeaderFiltering(apiRef, props);
Expand Down
8 changes: 3 additions & 5 deletions packages/x-data-grid-pro/src/components/GridPinnedRows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { getDataGridUtilityClass, gridClasses, useGridSelector } from '@mui/x-da
import {
GridPinnedRowsProps,
gridPinnedRowsSelector,
gridRenderContextSelector,
useGridPrivateApiContext,
} from '@mui/x-data-grid/internals';

Expand All @@ -20,18 +19,17 @@ export function GridPinnedRows({ position, virtualScroller }: GridPinnedRowsProp
const classes = useUtilityClasses();
const apiRef = useGridPrivateApiContext();

const renderContext = useGridSelector(apiRef, gridRenderContextSelector);
const pinnedRowsData = useGridSelector(apiRef, gridPinnedRowsSelector);
const rows = pinnedRowsData[position];

const pinnedRenderContext = React.useMemo(
() => ({
firstRowIndex: 0,
lastRowIndex: rows.length,
firstColumnIndex: renderContext.firstColumnIndex,
lastColumnIndex: renderContext.lastColumnIndex,
firstColumnIndex: -1,
lastColumnIndex: -1,
}),
[rows, renderContext.firstColumnIndex, renderContext.lastColumnIndex],
[rows],
);

if (rows.length === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import {
gridTabIndexColumnHeaderFilterSelector,
getDataGridUtilityClass,
GridFilterItem,
gridDimensionsSelector,
} from '@mui/x-data-grid';
import {
gridColumnsTotalWidthSelector,
gridHasFillerSelector,
gridHeaderFilterHeightSelector,
gridVerticalScrollbarWidthSelector,
useGridColumnHeaders as useGridColumnHeadersCommunity,
UseGridColumnHeadersProps,
GetHeadersParams,
Expand Down Expand Up @@ -69,9 +72,11 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
const rootProps = useGridRootProps();
const classes = useUtilityClasses(rootProps);
const disableHeaderFiltering = !rootProps.headerFilters;
const dimensions = useGridSelector(apiRef, gridDimensionsSelector);
const filterModel = useGridSelector(apiRef, gridFilterModelSelector);
const gridHasFiller = dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width;
const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector);
const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector);
const headerFilterHeight = useGridSelector(apiRef, gridHeaderFilterHeightSelector);
const scrollbarWidth = useGridSelector(apiRef, gridVerticalScrollbarWidthSelector);

const columnHeaderFilterFocus = useGridSelector(apiRef, gridFocusColumnHeaderFilterSelector);

Expand Down Expand Up @@ -120,13 +125,12 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
const item = getFilterItem(colDef);

const pinnedPosition = params?.position;
const scrollbarWidth = dimensions.hasScrollY ? dimensions.scrollbarSize : 0;
const pinnedOffset = getPinnedCellOffset(
pinnedPosition,
colDef.computedWidth,
columnIndex,
columnPositions,
dimensions.columnsTotalWidth,
columnsTotalWidth,
scrollbarWidth,
);

Expand All @@ -146,7 +150,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
<rootProps.slots.headerFilterCell
colIndex={columnIndex}
key={`${colDef.field}-filter`}
height={dimensions.headerFilterHeight}
height={headerFilterHeight}
width={colDef.computedWidth}
colDef={colDef}
hasFocus={hasFocus}
Expand Down
Loading