From c6b6c5d7093644112868fb6644f264e63e062260 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Thu, 30 May 2024 04:26:48 -0400 Subject: [PATCH] [DataGrid] Avoid re-rendering all cells on column change (#12980) --- .../column-menu/ColumnMenuGridPremiumSnap.js | 7 +++- .../column-menu/ColumnMenuGridPremiumSnap.tsx | 7 +++- .../src/components/cell/GridCell.tsx | 2 +- .../GridGenericColumnHeaderItem.tsx | 7 ---- .../features/columns/gridColumnsUtils.ts | 38 +++++++++++-------- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.js b/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.js index 8295de57e9dc..8fcabe12685f 100644 --- a/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.js +++ b/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.js @@ -32,8 +32,11 @@ export default function ColumnMenuGridPremiumSnap() { }); React.useEffect(() => { - apiRef.current.showColumnMenu('gross'); - console.log('after showColumnMenu'); + // To avoid an issue around Popper being open before the ref is set. + Promise.resolve().then(() => { + apiRef.current.showColumnMenu('gross'); + console.log('after showColumnMenu'); + }); }, [apiRef]); return ( diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.tsx b/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.tsx index 8295de57e9dc..8fcabe12685f 100644 --- a/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.tsx +++ b/docs/data/data-grid/column-menu/ColumnMenuGridPremiumSnap.tsx @@ -32,8 +32,11 @@ export default function ColumnMenuGridPremiumSnap() { }); React.useEffect(() => { - apiRef.current.showColumnMenu('gross'); - console.log('after showColumnMenu'); + // To avoid an issue around Popper being open before the ref is set. + Promise.resolve().then(() => { + apiRef.current.showColumnMenu('gross'); + console.log('after showColumnMenu'); + }); }, [apiRef]); return ( diff --git a/packages/x-data-grid/src/components/cell/GridCell.tsx b/packages/x-data-grid/src/components/cell/GridCell.tsx index 1864709f9348..2a196dccb5a7 100644 --- a/packages/x-data-grid/src/components/cell/GridCell.tsx +++ b/packages/x-data-grid/src/components/cell/GridCell.tsx @@ -146,7 +146,7 @@ let warnedOnce = false; // TODO(v7): Removing the wrapper will break the docs performance visualization demo. -const GridCell = React.forwardRef((props, ref) => { +const GridCell = React.forwardRef(function GridCell(props, ref) { const { column, rowId, diff --git a/packages/x-data-grid/src/components/columnHeaders/GridGenericColumnHeaderItem.tsx b/packages/x-data-grid/src/components/columnHeaders/GridGenericColumnHeaderItem.tsx index 7b1111733f9e..f7a9978c767e 100644 --- a/packages/x-data-grid/src/components/columnHeaders/GridGenericColumnHeaderItem.tsx +++ b/packages/x-data-grid/src/components/columnHeaders/GridGenericColumnHeaderItem.tsx @@ -76,7 +76,6 @@ const GridGenericColumnHeaderItem = React.forwardRef(function GridGenericColumnH const apiRef = useGridPrivateApiContext(); const rootProps = useGridRootProps(); const headerCellRef = React.useRef(null); - const [showColumnMenuIcon, setShowColumnMenuIcon] = React.useState(columnMenuOpen); const handleRef = useForkRef(headerCellRef, ref); @@ -85,12 +84,6 @@ const GridGenericColumnHeaderItem = React.forwardRef(function GridGenericColumnH ariaSort = sortDirection === 'asc' ? 'ascending' : 'descending'; } - React.useEffect(() => { - if (!showColumnMenuIcon) { - setShowColumnMenuIcon(columnMenuOpen); - } - }, [showColumnMenuIcon, columnMenuOpen]); - React.useLayoutEffect(() => { const columnMenuState = apiRef.current.state.columnMenu; if (hasFocus && !columnMenuState.open) { diff --git a/packages/x-data-grid/src/hooks/features/columns/gridColumnsUtils.ts b/packages/x-data-grid/src/hooks/features/columns/gridColumnsUtils.ts index 9126960acde7..cd3c0d8d42ce 100644 --- a/packages/x-data-grid/src/hooks/features/columns/gridColumnsUtils.ts +++ b/packages/x-data-grid/src/hooks/features/columns/gridColumnsUtils.ts @@ -171,30 +171,36 @@ export const hydrateColumnsWidth = ( const flexColumns: GridStateColDef[] = []; // For the non-flex columns, compute their width - // For the flex columns, compute there minimum width and how much width must be allocated during the flex allocation + // For the flex columns, compute their minimum width and how much width must be allocated during the flex allocation rawState.orderedFields.forEach((columnField) => { - const newColumn = { ...rawState.lookup[columnField] } as GridStateColDef; - if (rawState.columnVisibilityModel[columnField] === false) { - newColumn.computedWidth = 0; - } else { - let computedWidth: number; - if (newColumn.flex && newColumn.flex > 0) { - totalFlexUnits += newColumn.flex; - computedWidth = 0; - flexColumns.push(newColumn); + let column = rawState.lookup[columnField] as GridStateColDef; + let computedWidth = 0; + let isFlex = false; + + if (rawState.columnVisibilityModel[columnField] !== false) { + if (column.flex && column.flex > 0) { + totalFlexUnits += column.flex; + isFlex = true; } else { computedWidth = clamp( - newColumn.width || GRID_STRING_COL_DEF.width!, - newColumn.minWidth || GRID_STRING_COL_DEF.minWidth!, - newColumn.maxWidth || GRID_STRING_COL_DEF.maxWidth!, + column.width || GRID_STRING_COL_DEF.width!, + column.minWidth || GRID_STRING_COL_DEF.minWidth!, + column.maxWidth || GRID_STRING_COL_DEF.maxWidth!, ); } widthAllocatedBeforeFlex += computedWidth; - newColumn.computedWidth = computedWidth; } - columnsLookup[columnField] = newColumn; + if (column.computedWidth !== computedWidth) { + column = { ...column, computedWidth }; + } + + if (isFlex) { + flexColumns.push(column); + } + + columnsLookup[columnField] = column; }); const availableWidth = @@ -382,7 +388,7 @@ export const createColumnsState = ({ if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) { Object.keys(columnsState.lookup).forEach((field) => { - if (!columnsToKeep![field]) { + if (!columnsToKeep[field]) { delete columnsState.lookup[field]; } });