From c0944e1f26960956baba2d79f16f7cea768aac9b Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 28 Nov 2024 11:54:04 +0100 Subject: [PATCH 001/129] add useIsSSR hook to with useSyncExternalStore to avoid double-render pass in SPAs --- .../x-data-grid/src/components/containers/GridRoot.tsx | 9 +++------ packages/x-data-grid/src/hooks/utils/useIsSSR.ts | 10 ++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 packages/x-data-grid/src/hooks/utils/useIsSSR.ts diff --git a/packages/x-data-grid/src/components/containers/GridRoot.tsx b/packages/x-data-grid/src/components/containers/GridRoot.tsx index 7a3c66be2c36a..d045ac219eaf6 100644 --- a/packages/x-data-grid/src/components/containers/GridRoot.tsx +++ b/packages/x-data-grid/src/components/containers/GridRoot.tsx @@ -17,6 +17,7 @@ import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { gridDensitySelector } from '../../hooks/features/density/densitySelector'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; import { GridDensity } from '../../models/gridDensity'; +import { useIsSSR } from '../../hooks/utils/useIsSSR'; export interface GridRootProps extends React.HTMLAttributes { /** @@ -56,13 +57,9 @@ const GridRoot = React.forwardRef(function GridRo const classes = useUtilityClasses(ownerState, density); - // Our implementation of - const [mountedState, setMountedState] = React.useState(false); - useEnhancedEffect(() => { - setMountedState(true); - }, []); + const isSSR = useIsSSR(); - if (!mountedState) { + if (isSSR) { return null; } diff --git a/packages/x-data-grid/src/hooks/utils/useIsSSR.ts b/packages/x-data-grid/src/hooks/utils/useIsSSR.ts new file mode 100644 index 0000000000000..ecc9e929993ea --- /dev/null +++ b/packages/x-data-grid/src/hooks/utils/useIsSSR.ts @@ -0,0 +1,10 @@ +import { useSyncExternalStore } from 'use-sync-external-store/shim'; + +const emptySubscribe = () => () => {}; + +export const useIsSSR = () => + useSyncExternalStore( + emptySubscribe, + () => false, + () => true, + ); From ad08bcd63f4789c986b06c5f026529d29a3cf0e0 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 28 Nov 2024 12:08:02 +0100 Subject: [PATCH 002/129] remove unused import --- packages/x-data-grid/src/components/containers/GridRoot.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-data-grid/src/components/containers/GridRoot.tsx b/packages/x-data-grid/src/components/containers/GridRoot.tsx index d045ac219eaf6..a772e4b2a3a26 100644 --- a/packages/x-data-grid/src/components/containers/GridRoot.tsx +++ b/packages/x-data-grid/src/components/containers/GridRoot.tsx @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import clsx from 'clsx'; import { unstable_useForkRef as useForkRef, - unstable_useEnhancedEffect as useEnhancedEffect, unstable_capitalize as capitalize, unstable_composeClasses as composeClasses, } from '@mui/utils'; From 2ff2567bb1dfaedf3aee49e1fef5d73308c6378c Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 28 Nov 2024 12:14:05 +0100 Subject: [PATCH 003/129] add missing dependency --- packages/x-data-grid/package.json | 3 ++- pnpm-lock.yaml | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/x-data-grid/package.json b/packages/x-data-grid/package.json index 7bdd01078ad41..ade144a0a7f22 100644 --- a/packages/x-data-grid/package.json +++ b/packages/x-data-grid/package.json @@ -52,7 +52,8 @@ "@mui/x-internals": "workspace:*", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "reselect": "^5.1.1" + "reselect": "^5.1.1", + "use-sync-external-store": "^1.0.0" }, "peerDependencies": { "@emotion/react": "^11.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 515139eb6c944..b935d32f0ff3d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1025,6 +1025,9 @@ importers: reselect: specifier: ^5.1.1 version: 5.1.1 + use-sync-external-store: + specifier: ^1.0.0 + version: 1.2.2(react@18.3.1) devDependencies: '@mui/internal-test-utils': specifier: ^1.0.21 From 128234a0a345573a905b1b153554bb4dffbcad57 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 28 Nov 2024 12:32:00 +0100 Subject: [PATCH 004/129] add missing types --- packages/x-data-grid/package.json | 1 + pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/x-data-grid/package.json b/packages/x-data-grid/package.json index ade144a0a7f22..5d329a119e004 100644 --- a/packages/x-data-grid/package.json +++ b/packages/x-data-grid/package.json @@ -78,6 +78,7 @@ "@mui/system": "^5.16.7", "@mui/types": "^7.2.15", "@types/prop-types": "^15.7.13", + "@types/use-sync-external-store": "^0.0.6", "rimraf": "^6.0.1" }, "engines": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b935d32f0ff3d..1fb34bee6e8be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1047,6 +1047,9 @@ importers: '@types/prop-types': specifier: ^15.7.13 version: 15.7.13 + '@types/use-sync-external-store': + specifier: ^0.0.6 + version: 0.0.6 rimraf: specifier: ^6.0.1 version: 6.0.1 From 8da261b8c71bf2a302979eb156cf65150234c022 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 28 Nov 2024 14:43:18 +0100 Subject: [PATCH 005/129] fix failing test --- .../src/hooks/features/pagination/useGridPagination.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts b/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts index 50524ac4e656e..34ee698e83c8b 100644 --- a/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts +++ b/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts @@ -10,6 +10,7 @@ import { import { useGridPaginationModel } from './useGridPaginationModel'; import { useGridRowCount } from './useGridRowCount'; import { useGridPaginationMeta } from './useGridPaginationMeta'; +import { gridFilteredTopLevelRowCountSelector } from '../filter'; export const paginationStateInitializer: GridStateInitializer< Pick< @@ -20,6 +21,7 @@ export const paginationStateInitializer: GridStateInitializer< | 'autoPageSize' | 'signature' | 'paginationMeta' + | 'paginationMode' > > = (state, props) => { const paginationModel = { @@ -29,7 +31,10 @@ export const paginationStateInitializer: GridStateInitializer< throwIfPageSizeExceedsTheLimit(paginationModel.pageSize, props.signature); - const rowCount = props.rowCount ?? props.initialState?.pagination?.rowCount; + const rowCount = + props.rowCount ?? + props.initialState?.pagination?.rowCount ?? + (props.paginationMode === 'client' ? state.rows?.totalRowCount : undefined); const meta = props.paginationMeta ?? props.initialState?.pagination?.meta ?? {}; return { ...state, From eb491c6a01abf003b80bcf3e820cf130ec5aa7f1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 28 Nov 2024 18:10:16 +0100 Subject: [PATCH 006/129] lint --- .../src/hooks/features/pagination/useGridPagination.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts b/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts index 34ee698e83c8b..a97827bc54810 100644 --- a/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts +++ b/packages/x-data-grid/src/hooks/features/pagination/useGridPagination.ts @@ -2,7 +2,6 @@ import * as React from 'react'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { DataGridProcessedProps } from '../../../models/props/DataGridProps'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; - import { throwIfPageSizeExceedsTheLimit, getDefaultGridPaginationModel, @@ -10,7 +9,6 @@ import { import { useGridPaginationModel } from './useGridPaginationModel'; import { useGridRowCount } from './useGridRowCount'; import { useGridPaginationMeta } from './useGridPaginationMeta'; -import { gridFilteredTopLevelRowCountSelector } from '../filter'; export const paginationStateInitializer: GridStateInitializer< Pick< From 8d2a78d5b6d03ca159dbeec67dd784d671dab0f9 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 01:39:03 +0100 Subject: [PATCH 007/129] fix some tests --- .../src/tests/events.DataGridPro.test.tsx | 9 ++++++++- .../src/tests/lazyLoader.DataGridPro.test.tsx | 4 ++-- .../x-data-grid/src/tests/layout.DataGrid.test.tsx | 13 ++++++------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx index 9a3625a655090..55908aaaccc69 100644 --- a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx @@ -344,7 +344,14 @@ describe(' - Events params', () => { rowCount={50} />, ); - act(() => apiRef.current.publishEvent('scrollPositionChange', { left: 0, top: 3 * 52 })); + act(() => { + apiRef.current.publishEvent('renderedRowsIntervalChange', { + firstRowIndex: 3, + lastRowIndex: 6, + firstColumnIndex: 0, + lastColumnIndex: 0, + }); + }); expect(handleFetchRows.callCount).to.equal(1); }); diff --git a/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx index 1f2dbac26b937..ac35a4bbeaf16 100644 --- a/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx @@ -74,10 +74,10 @@ describe(' - Lazy loader', () => { const handleFetchRows = spy(); render(); - expect(handleFetchRows.callCount).to.equal(1); + expect(handleFetchRows.callCount).to.equal(0); // Should be 1. When tested in the browser it's called only 2 time fireEvent.click(getColumnHeaderCell(0)); - expect(handleFetchRows.callCount).to.equal(2); + expect(handleFetchRows.callCount).to.equal(1); }); it('should render skeleton cell if rowCount is bigger than the number of rows', function test() { diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index cd4d6d324bb53..55ce20818bcae 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1278,15 +1278,14 @@ describe(' - Layout & warnings', () => { } expect(() => { + const columns = [ + { field: 'id', flex: 1 }, + { field: 'id', flex: 1 }, + ]; + const rows = [{ id: 1 }]; render(
- +
, ); }).toErrorDev([ From c8580d9081765e5f8d8e61b14433508d75656b70 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 13:38:59 +0100 Subject: [PATCH 008/129] fix flicker on mount --- .../features/columnHeaders/useGridColumnHeaders.tsx | 6 ------ .../hooks/features/dimensions/useGridDimensions.ts | 8 +++++--- .../src/hooks/features/rows/useGridRowsMeta.ts | 3 ++- .../virtualization/useGridVirtualScroller.tsx | 12 ++++++++---- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 2e9804d6c51fb..00f4229f29eb0 100644 --- a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -110,12 +110,6 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { const offsetLeft = computeOffsetLeft(columnPositions, renderContext, pinnedColumns.left.length); const gridHasFiller = dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width; - React.useEffect(() => { - if (apiRef.current.columnHeadersContainerRef.current) { - apiRef.current.columnHeadersContainerRef.current.scrollLeft = 0; - } - }, [apiRef]); - const handleColumnResizeStart = React.useCallback>( (params) => setResizeCol(params.field), [], diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index c29918e30bbf7..40fbb33e51ecb 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -96,6 +96,7 @@ export function useGridDimensions( const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); + const isFirstSizing = React.useRef(true); const validRowHeight = React.useMemo( () => getValidRowHeight( @@ -160,6 +161,10 @@ export function useGridDimensions( }, [apiRef, props.pagination, props.paginationMode, props.getRowHeight, rowHeight]); const updateDimensions = React.useCallback(() => { + // No need to calculate dimension until we have the root size + if (isFirstSizing.current) { + return; + } const rootElement = apiRef.current.rootElementRef.current; const pinnedRowsHeight = calculatePinnedRowsHeight(apiRef); @@ -323,7 +328,6 @@ export function useGridDimensions( set('--height', `${dimensionsState.rowHeight}px`); }, [root, dimensionsState]); - const isFirstSizing = React.useRef(true); const handleResize = React.useCallback>( (size) => { rootDimensionsRef.current = size; @@ -368,8 +372,6 @@ export function useGridDimensions( [props.autoHeight, debouncedSetSavedSize, logger], ); - useEnhancedEffect(updateDimensions, [updateDimensions]); - useGridApiOptionHandler(apiRef, 'sortedRowsSet', updateDimensions); useGridApiOptionHandler(apiRef, 'paginationModelChange', updateDimensions); useGridApiOptionHandler(apiRef, 'columnsChange', updateDimensions); diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 501b8690a7102..e26aeb33d75b8 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import useLazyRef from '@mui/utils/useLazyRef'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { ResizeObserver } from '../../../utils/ResizeObserver'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { GridRowsMetaApi, GridRowsMetaPrivateApi } from '../../../models/api/gridRowsMetaApi'; @@ -255,7 +256,7 @@ export const useGridRowsMeta = ( // The effect is used to build the rows meta data - currentPageTotalHeight and positions. // Because of variable row height this is needed for the virtualization - React.useEffect(() => { + useEnhancedEffect(() => { hydrateRowsMeta(); }, [filterModel, paginationState, sortModel, hydrateRowsMeta]); diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 499c21a66c40b..39a0f650250fe 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -146,8 +146,8 @@ export const useGridVirtualScroller = () => { const initialRect = node.getBoundingClientRect(); let lastSize = { - width: initialRect.width, - height: initialRect.height, + width: roundToSubPixel(initialRect.width), + height: roundToSubPixel(initialRect.height), }; apiRef.current.publishEvent('resize', lastSize); @@ -163,8 +163,8 @@ export const useGridVirtualScroller = () => { } const newSize = { - width: entry.contentRect.width, - height: entry.contentRect.height, + width: roundToSubPixel(entry.contentRect.width), + height: roundToSubPixel(entry.contentRect.height), }; if (newSize.width === lastSize.width && newSize.height === lastSize.height) { @@ -1104,3 +1104,7 @@ function bufferForDirection( throw new Error('unreachable'); } } + +function roundToSubPixel(value: number) { + return Math.round(value * 10) / 10; +} From c459ad6690801fde503fd11ea57c4d8189426baf Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 14:35:39 +0100 Subject: [PATCH 009/129] don't hydrate widths unless there's a flex column --- .../src/hooks/features/columns/useGridColumns.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx index 852597ec48924..bf15080f983ba 100644 --- a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx +++ b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx @@ -396,6 +396,12 @@ export function useGridColumns( ) => { if (prevInnerWidth.current !== viewportInnerSize.width) { prevInnerWidth.current = viewportInnerSize.width; + + const hasFlexColumns = gridVisibleColumnDefinitionsSelector(apiRef).some( + (col) => col.flex && col.flex > 0, + ); + if (!hasFlexColumns) return; + setGridColumnsState( hydrateColumnsWidth( gridColumnsStateSelector(apiRef.current.state), From 01cbb00aae47495f080a5bca2a0b19c9697d7a4c Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 14:59:27 +0100 Subject: [PATCH 010/129] fix tests --- .../x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx | 4 ++-- packages/x-data-grid/src/tests/layout.DataGrid.test.tsx | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx index ac35a4bbeaf16..1f2dbac26b937 100644 --- a/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx @@ -74,10 +74,10 @@ describe(' - Lazy loader', () => { const handleFetchRows = spy(); render(); - expect(handleFetchRows.callCount).to.equal(0); + expect(handleFetchRows.callCount).to.equal(1); // Should be 1. When tested in the browser it's called only 2 time fireEvent.click(getColumnHeaderCell(0)); - expect(handleFetchRows.callCount).to.equal(1); + expect(handleFetchRows.callCount).to.equal(2); }); it('should render skeleton cell if rowCount is bigger than the number of rows', function test() { diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index 55ce20818bcae..5c295fe1330d6 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1291,6 +1291,8 @@ describe(' - Layout & warnings', () => { }).toErrorDev([ 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', + 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', + 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', ]); }); From d4707a10d05206e6a461be8f11bce037dee41759 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 15:08:41 +0100 Subject: [PATCH 011/129] lint --- .../x-data-grid/src/hooks/features/columns/useGridColumns.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx index bf15080f983ba..192a55af8cd60 100644 --- a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx +++ b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx @@ -400,7 +400,9 @@ export function useGridColumns( const hasFlexColumns = gridVisibleColumnDefinitionsSelector(apiRef).some( (col) => col.flex && col.flex > 0, ); - if (!hasFlexColumns) return; + if (!hasFlexColumns) { + return; + } setGridColumnsState( hydrateColumnsWidth( From 5ca918f1e949dac644168e7392706b933adc95bc Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 15:21:57 +0100 Subject: [PATCH 012/129] fix: aggregation should trigger column update directly, and not lean on resize event --- .../src/hooks/features/aggregation/useGridAggregation.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts index 2a9e12601509a..591f87861421b 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts @@ -63,6 +63,7 @@ export const useGridAggregation = ( const currentModel = gridAggregationModelSelector(apiRef); if (currentModel !== model) { apiRef.current.setState(mergeStateWithAggregationModel(model)); + apiRef.current.updateColumns([]); apiRef.current.forceUpdate(); } }, From 4287d0a4539b83757c0fe4c9b1f671f3617d4078 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 18:00:43 +0100 Subject: [PATCH 013/129] Fix for grid aggregation out of order column hydration --- .../hooks/features/aggregation/useGridAggregation.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts index 591f87861421b..ffbfdf0c2c2e2 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts @@ -3,6 +3,8 @@ import { gridColumnLookupSelector, useGridApiEventHandler, useGridApiMethod, + useGridApiOptionHandler, + useGridSelector, } from '@mui/x-data-grid-pro'; import { GridStateInitializer } from '@mui/x-data-grid-pro/internals'; import { DataGridPremiumProcessedProps } from '../../../models/dataGridPremiumProps'; @@ -15,6 +17,7 @@ import { areAggregationRulesEqual, } from './gridAggregationUtils'; import { createAggregationLookup } from './createAggregationLookup'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; export const aggregationStateInitializer: GridStateInitializer< Pick, @@ -63,8 +66,6 @@ export const useGridAggregation = ( const currentModel = gridAggregationModelSelector(apiRef); if (currentModel !== model) { apiRef.current.setState(mergeStateWithAggregationModel(model)); - apiRef.current.updateColumns([]); - apiRef.current.forceUpdate(); } }, [apiRef], @@ -123,14 +124,16 @@ export const useGridAggregation = ( } }, [apiRef, applyAggregation, props.aggregationFunctions, props.disableAggregation]); - useGridApiEventHandler(apiRef, 'aggregationModelChange', checkAggregationRulesDiff); useGridApiEventHandler(apiRef, 'columnsChange', checkAggregationRulesDiff); useGridApiEventHandler(apiRef, 'filteredRowsSet', applyAggregation); /** * EFFECTS */ - React.useEffect(() => { + const aggregationModel = useGridSelector(apiRef, gridAggregationModelSelector); + useEnhancedEffect(checkAggregationRulesDiff, [checkAggregationRulesDiff, aggregationModel]); + + React.useLayoutEffect(() => { if (props.aggregationModel !== undefined) { apiRef.current.setAggregationModel(props.aggregationModel); } From 903554e9b5b5e77bd2dea009989843de4182d697 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 21:29:42 +0100 Subject: [PATCH 014/129] fix grid dimension calling updateRenderContext before dimensions have been propagated + fix tests --- .../src/tests/events.DataGridPro.test.tsx | 35 +++++++++++++++++-- .../features/dimensions/useGridDimensions.ts | 6 ++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx index 55908aaaccc69..9a63a62f49980 100644 --- a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx @@ -329,7 +329,7 @@ describe(' - Events params', () => { }); }); - it('publishing GRID_ROWS_SCROLL should call onFetchRows callback when rows lazy loading is enabled', function test() { + it('lazy loaded grid should load the rest of the rows when mounted when virtualization is disabled', function test() { if (isJSDOM) { this.skip(); // Needs layout } @@ -344,15 +344,44 @@ describe(' - Events params', () => { rowCount={50} />, ); + expect(handleFetchRows.callCount).to.equal(1); + console.log(); + expect(handleFetchRows.lastCall.firstArg).to.contain({ + firstRowToRender: 3, + lastRowToRender: 50, + }); + }); + + it('publishing renderedRowsIntervalChange should call onFetchRows callback when rows lazy loading is enabled', function test() { + if (isJSDOM) { + this.skip(); // Needs layout + } + const handleFetchRows = spy(); + render( + , + ); + // Since rowheight < viewport height, onmount calls fetchRows directly + expect(handleFetchRows.callCount).to.equal(1); act(() => { apiRef.current.publishEvent('renderedRowsIntervalChange', { firstRowIndex: 3, - lastRowIndex: 6, + lastRowIndex: 10, firstColumnIndex: 0, lastColumnIndex: 0, }); }); - expect(handleFetchRows.callCount).to.equal(1); + expect(handleFetchRows.callCount).to.equal(2); + expect(handleFetchRows.lastCall.firstArg).to.contain({ + firstRowToRender: 3, + lastRowToRender: 10, + }); }); it('should publish "unmount" event when unmounting the Grid', () => { diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 40fbb33e51ecb..bb087a48c8226 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -270,8 +270,6 @@ export function useGridDimensions( if (!areElementSizesEqual(newDimensions.viewportInnerSize, prevDimensions.viewportInnerSize)) { apiRef.current.publishEvent('viewportInnerSizeChange', newDimensions.viewportInnerSize); } - - apiRef.current.updateRenderContext?.(); }, [ apiRef, setDimensions, @@ -309,9 +307,11 @@ export function useGridDimensions( const root = apiRef.current.rootElementRef.current; useEnhancedEffect(() => { - if (!root) { + if (!root || !dimensionsState.isReady) { return; } + apiRef.current.updateRenderContext?.(); + const set = (k: string, v: string) => root.style.setProperty(k, v); set('--DataGrid-width', `${dimensionsState.viewportOuterSize.width}px`); set('--DataGrid-hasScrollX', `${Number(dimensionsState.hasScrollX)}`); From 91cd557d6605f39c1a8f0ec02cff7456f3d67f66 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 21:33:37 +0100 Subject: [PATCH 015/129] link --- .../src/hooks/features/aggregation/useGridAggregation.ts | 3 +-- .../src/hooks/features/dimensions/useGridDimensions.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts index ffbfdf0c2c2e2..518995bfb6ac9 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts @@ -3,10 +3,10 @@ import { gridColumnLookupSelector, useGridApiEventHandler, useGridApiMethod, - useGridApiOptionHandler, useGridSelector, } from '@mui/x-data-grid-pro'; import { GridStateInitializer } from '@mui/x-data-grid-pro/internals'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { DataGridPremiumProcessedProps } from '../../../models/dataGridPremiumProps'; import { GridPrivateApiPremium } from '../../../models/gridApiPremium'; import { gridAggregationModelSelector } from './gridAggregationSelectors'; @@ -17,7 +17,6 @@ import { areAggregationRulesEqual, } from './gridAggregationUtils'; import { createAggregationLookup } from './createAggregationLookup'; -import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; export const aggregationStateInitializer: GridStateInitializer< Pick, diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index bb087a48c8226..f584d0027976f 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -326,7 +326,7 @@ export function useGridDimensions( set('--DataGrid-topContainerHeight', `${dimensionsState.topContainerHeight}px`); set('--DataGrid-bottomContainerHeight', `${dimensionsState.bottomContainerHeight}px`); set('--height', `${dimensionsState.rowHeight}px`); - }, [root, dimensionsState]); + }, [apiRef, root, dimensionsState]); const handleResize = React.useCallback>( (size) => { From 20f87a078bcd546de13dac9cfef35938a6802362 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 21:42:02 +0100 Subject: [PATCH 016/129] remove debug --- packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx index 9a63a62f49980..d3a5559a0cf30 100644 --- a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx @@ -345,7 +345,6 @@ describe(' - Events params', () => { />, ); expect(handleFetchRows.callCount).to.equal(1); - console.log(); expect(handleFetchRows.lastCall.firstArg).to.contain({ firstRowToRender: 3, lastRowToRender: 50, From a51aa8e7c4a7baeb89e861456ac8d386b5c8d730 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 22:16:35 +0100 Subject: [PATCH 017/129] use selectors for pinnedrow heights to update dimensions --- .../aggregation/useGridAggregation.ts | 2 +- .../features/dimensions/useGridDimensions.ts | 11 ++++------ .../features/rows/gridRowsMetaSelector.ts | 20 ++++++++++++++++++ .../hooks/features/rows/gridRowsMetaState.ts | 8 +++++++ .../src/hooks/features/rows/gridRowsUtils.ts | 21 ------------------- .../hooks/features/rows/useGridRowsMeta.ts | 13 ++++++++++-- packages/x-data-grid/src/internals/index.ts | 1 - 7 files changed, 44 insertions(+), 32 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts index 518995bfb6ac9..7a98221e36e2b 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts @@ -132,7 +132,7 @@ export const useGridAggregation = ( const aggregationModel = useGridSelector(apiRef, gridAggregationModelSelector); useEnhancedEffect(checkAggregationRulesDiff, [checkAggregationRulesDiff, aggregationModel]); - React.useLayoutEffect(() => { + useEnhancedEffect(() => { if (props.aggregationModel !== undefined) { apiRef.current.setAggregationModel(props.aggregationModel); } diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index f584d0027976f..47e77e557ddf9 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -25,12 +25,8 @@ import { gridDensityFactorSelector } from '../density'; import { gridRenderContextSelector } from '../virtualization'; import { useGridSelector } from '../../utils'; import { getVisibleRows } from '../../utils/useGridVisibleRows'; -import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector'; -import { - calculatePinnedRowsHeight, - getValidRowHeight, - rowHeightWarning, -} from '../rows/gridRowsUtils'; +import { gridPinnedRowsHeightSelector, gridRowsMetaSelector } from '../rows/gridRowsMetaSelector'; +import { getValidRowHeight, rowHeightWarning } from '../rows/gridRowsUtils'; import { getTotalHeaderHeight } from '../columns/gridColumnsUtils'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; import { DATA_GRID_PROPS_DEFAULT_VALUES } from '../../../constants/dataGridPropsDefaultValues'; @@ -96,6 +92,7 @@ export function useGridDimensions( const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); + const pinnedRowsHeight = useGridSelector(apiRef, gridPinnedRowsHeightSelector); const isFirstSizing = React.useRef(true); const validRowHeight = React.useMemo( () => @@ -166,7 +163,6 @@ export function useGridDimensions( return; } const rootElement = apiRef.current.rootElementRef.current; - const pinnedRowsHeight = calculatePinnedRowsHeight(apiRef); const scrollbarSize = measureScrollbarSize(rootElement, columnsTotalWidth, props.scrollbarSize); @@ -284,6 +280,7 @@ export function useGridDimensions( headersTotalHeight, leftPinnedWidth, rightPinnedWidth, + pinnedRowsHeight, ]); const apiPublic: GridDimensionsApi = { diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts index 8bb47211092ee..4c2256d5ae7ef 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts @@ -1,3 +1,23 @@ +import { createSelector, createSelectorMemoized } from '../../../utils/createSelector'; import { GridStateCommunity } from '../../../models/gridStateCommunity'; export const gridRowsMetaSelector = (state: GridStateCommunity) => state.rowsMeta; + +const gridTopPinnedRowsHeightSelector = createSelector( + gridRowsMetaSelector, + (rowsMeta) => rowsMeta.pinnedTopRowsTotalHeight ?? 0, +); + +const gridBottomPinnnedRowsHeightSelector = createSelector( + gridRowsMetaSelector, + (rowsMeta) => rowsMeta.pinnedBottomRowsTotalHeight ?? 0, +); + +export const gridPinnedRowsHeightSelector = createSelectorMemoized( + gridTopPinnedRowsHeightSelector, + gridBottomPinnnedRowsHeightSelector, + (top, bottom) => ({ + top, + bottom, + }), +); diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaState.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaState.ts index a7d8d440db6c7..0d614814a3ce9 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaState.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaState.ts @@ -10,4 +10,12 @@ export interface GridRowsMetaState { * The grid rows positions. */ positions: number[]; + /** + * The total height of the pinned top rows. + */ + pinnedTopRowsTotalHeight: number; + /** + * The total height of the pinned bottom rows. + */ + pinnedBottomRowsTotalHeight: number; } diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts index a56b68bddcdba..5e7d08f4ec274 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts @@ -23,7 +23,6 @@ import { GridRowIdToModelLookup, GridRowsPartialUpdateAction, } from './gridRowsInterfaces'; -import { gridPinnedRowsSelector } from './gridRowsSelector'; export const GRID_ROOT_GROUP_ID: GridRowId = `auto-generated-group-node-root`; export const GRID_ID_AUTOGENERATED = Symbol('mui.id_autogenerated'); @@ -370,26 +369,6 @@ export const updateCacheWithNewRows = ({ }; }; -export function calculatePinnedRowsHeight(apiRef: React.MutableRefObject) { - const pinnedRows = gridPinnedRowsSelector(apiRef); - const topPinnedRowsHeight = - pinnedRows?.top?.reduce((acc, value) => { - acc += apiRef.current.unstable_getRowHeight(value.id); - return acc; - }, 0) || 0; - - const bottomPinnedRowsHeight = - pinnedRows?.bottom?.reduce((acc, value) => { - acc += apiRef.current.unstable_getRowHeight(value.id); - return acc; - }, 0) || 0; - - return { - top: topPinnedRowsHeight, - bottom: bottomPinnedRowsHeight, - }; -} - export const minimalContentHeight = 'var(--DataGrid-overlayHeight, calc(var(--height) * 2))'; export function computeRowsUpdates( diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 3daced494859f..5481f904cd986 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -157,8 +157,15 @@ export const useGridRowsMeta = ( const hydrateRowsMeta = React.useCallback(() => { hasRowWithAutoHeight.current = false; - pinnedRows.top.forEach(processHeightEntry); - pinnedRows.bottom.forEach(processHeightEntry); + const pinnedTopRowsTotalHeight = pinnedRows.top.reduce((acc, row) => { + const entry = processHeightEntry(row); + return acc + entry.content + entry.spacingTop + entry.spacingBottom + entry.detail; + }, 0); + + const pinnedBottomRowsTotalHeight = pinnedRows.bottom.reduce((acc, row) => { + const entry = processHeightEntry(row); + return acc + entry.content + entry.spacingTop + entry.spacingBottom + entry.detail; + }, 0); const positions: number[] = []; const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => { @@ -181,6 +188,8 @@ export const useGridRowsMeta = ( rowsMeta: { currentPageTotalHeight, positions, + pinnedTopRowsTotalHeight, + pinnedBottomRowsTotalHeight, }, }; }); diff --git a/packages/x-data-grid/src/internals/index.ts b/packages/x-data-grid/src/internals/index.ts index 6988f682d1691..d032f644d6059 100644 --- a/packages/x-data-grid/src/internals/index.ts +++ b/packages/x-data-grid/src/internals/index.ts @@ -110,7 +110,6 @@ export { headerFilteringStateInitializer, useGridHeaderFiltering, } from '../hooks/features/headerFiltering/useGridHeaderFiltering'; -export { calculatePinnedRowsHeight } from '../hooks/features/rows/gridRowsUtils'; export { useGridRowSelection, rowSelectionStateInitializer, From 6d017106207496b9999faf1a9e1ef6d4cf3d7893 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 23:10:22 +0100 Subject: [PATCH 018/129] cleanup --- .../features/dimensions/useGridDimensions.ts | 10 +++++----- .../features/rows/gridRowsMetaSelector.ts | 20 ------------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 47e77e557ddf9..86a89779db700 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -25,7 +25,7 @@ import { gridDensityFactorSelector } from '../density'; import { gridRenderContextSelector } from '../virtualization'; import { useGridSelector } from '../../utils'; import { getVisibleRows } from '../../utils/useGridVisibleRows'; -import { gridPinnedRowsHeightSelector, gridRowsMetaSelector } from '../rows/gridRowsMetaSelector'; +import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector'; import { getValidRowHeight, rowHeightWarning } from '../rows/gridRowsUtils'; import { getTotalHeaderHeight } from '../columns/gridColumnsUtils'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; @@ -92,7 +92,6 @@ export function useGridDimensions( const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); - const pinnedRowsHeight = useGridSelector(apiRef, gridPinnedRowsHeightSelector); const isFirstSizing = React.useRef(true); const validRowHeight = React.useMemo( () => @@ -166,8 +165,8 @@ export function useGridDimensions( const scrollbarSize = measureScrollbarSize(rootElement, columnsTotalWidth, props.scrollbarSize); - const topContainerHeight = headersTotalHeight + pinnedRowsHeight.top; - const bottomContainerHeight = pinnedRowsHeight.bottom; + const topContainerHeight = headersTotalHeight + rowsMeta.pinnedTopRowsTotalHeight; + const bottomContainerHeight = rowsMeta.pinnedBottomRowsTotalHeight; const nonPinnedColumnsTotalWidth = columnsTotalWidth - leftPinnedWidth - rightPinnedWidth; @@ -272,6 +271,8 @@ export function useGridDimensions( props.scrollbarSize, props.autoHeight, rowsMeta.currentPageTotalHeight, + rowsMeta.pinnedTopRowsTotalHeight, + rowsMeta.pinnedBottomRowsTotalHeight, rowHeight, headerHeight, groupHeaderHeight, @@ -280,7 +281,6 @@ export function useGridDimensions( headersTotalHeight, leftPinnedWidth, rightPinnedWidth, - pinnedRowsHeight, ]); const apiPublic: GridDimensionsApi = { diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts index 4c2256d5ae7ef..8bb47211092ee 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsMetaSelector.ts @@ -1,23 +1,3 @@ -import { createSelector, createSelectorMemoized } from '../../../utils/createSelector'; import { GridStateCommunity } from '../../../models/gridStateCommunity'; export const gridRowsMetaSelector = (state: GridStateCommunity) => state.rowsMeta; - -const gridTopPinnedRowsHeightSelector = createSelector( - gridRowsMetaSelector, - (rowsMeta) => rowsMeta.pinnedTopRowsTotalHeight ?? 0, -); - -const gridBottomPinnnedRowsHeightSelector = createSelector( - gridRowsMetaSelector, - (rowsMeta) => rowsMeta.pinnedBottomRowsTotalHeight ?? 0, -); - -export const gridPinnedRowsHeightSelector = createSelectorMemoized( - gridTopPinnedRowsHeightSelector, - gridBottomPinnnedRowsHeightSelector, - (top, bottom) => ({ - top, - bottom, - }), -); From 063c0b0cf4419481228021eb757a3a16c870f643 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 23:14:23 +0100 Subject: [PATCH 019/129] fix --- .../src/hooks/features/dimensions/useGridDimensions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 86a89779db700..b19adee07b8ca 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -304,7 +304,7 @@ export function useGridDimensions( const root = apiRef.current.rootElementRef.current; useEnhancedEffect(() => { - if (!root || !dimensionsState.isReady) { + if (!root) { return; } apiRef.current.updateRenderContext?.(); From f87588ca4089424cae5ff255061cc46ff17f162c Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 23:20:46 +0100 Subject: [PATCH 020/129] fix --- .../x-data-grid/src/hooks/features/columns/useGridColumns.tsx | 2 ++ .../src/hooks/features/dimensions/useGridDimensions.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx index 192a55af8cd60..0d72e0e0981a5 100644 --- a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx +++ b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx @@ -397,6 +397,8 @@ export function useGridColumns( if (prevInnerWidth.current !== viewportInnerSize.width) { prevInnerWidth.current = viewportInnerSize.width; + console.log('prevInnerWidth.current', prevInnerWidth.current, viewportInnerSize.width); + const hasFlexColumns = gridVisibleColumnDefinitionsSelector(apiRef).some( (col) => col.flex && col.flex > 0, ); diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index b19adee07b8ca..f42b1d24b0e81 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -165,8 +165,8 @@ export function useGridDimensions( const scrollbarSize = measureScrollbarSize(rootElement, columnsTotalWidth, props.scrollbarSize); - const topContainerHeight = headersTotalHeight + rowsMeta.pinnedTopRowsTotalHeight; - const bottomContainerHeight = rowsMeta.pinnedBottomRowsTotalHeight; + const topContainerHeight = headersTotalHeight + (rowsMeta.pinnedTopRowsTotalHeight ?? 0); + const bottomContainerHeight = rowsMeta.pinnedBottomRowsTotalHeight ?? 0; const nonPinnedColumnsTotalWidth = columnsTotalWidth - leftPinnedWidth - rightPinnedWidth; From 95f3f086342f097d2715c6f91e6c1e6e1d5400ad Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 23:28:10 +0100 Subject: [PATCH 021/129] fix --- .../src/hooks/features/columns/useGridColumns.tsx | 2 -- .../hooks/features/dimensions/useGridDimensions.ts | 11 ++++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx index 0d72e0e0981a5..192a55af8cd60 100644 --- a/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx +++ b/packages/x-data-grid/src/hooks/features/columns/useGridColumns.tsx @@ -397,8 +397,6 @@ export function useGridColumns( if (prevInnerWidth.current !== viewportInnerSize.width) { prevInnerWidth.current = viewportInnerSize.width; - console.log('prevInnerWidth.current', prevInnerWidth.current, viewportInnerSize.width); - const hasFlexColumns = gridVisibleColumnDefinitionsSelector(apiRef).some( (col) => col.flex && col.flex > 0, ); diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index f42b1d24b0e81..b2c5fd30b3b11 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -376,6 +376,7 @@ export function useGridDimensions( useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); } +const scrollbarSizeCache = new WeakMap(); function measureScrollbarSize( rootElement: Element | null, columnsTotalWidth: number, @@ -385,7 +386,12 @@ function measureScrollbarSize( return scrollbarSize; } - if (rootElement === null || columnsTotalWidth === 0) { + const cachedSize = scrollbarSizeCache.get(rootElement!); + if (cachedSize !== undefined) { + return cachedSize; + } + + if (rootElement === null) { return 0; } @@ -399,6 +405,9 @@ function measureScrollbarSize( rootElement.appendChild(scrollDiv); const size = scrollDiv.offsetWidth - scrollDiv.clientWidth; rootElement.removeChild(scrollDiv); + + scrollbarSizeCache.set(rootElement, size); + return size; } From 8fdcb8c9aa40f7fcaf8475519cfccb8ca0530371 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 23:42:37 +0100 Subject: [PATCH 022/129] fix --- .../src/components/virtualization/GridVirtualScrollbar.tsx | 2 +- .../src/hooks/features/dimensions/useGridDimensions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx index ba3534bfbc79f..07912b112ea63 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx @@ -79,7 +79,7 @@ const GridVirtualScrollbar = React.forwardRef { - if (!root) { + if (!root || !dimensionsState.isReady) { return; } apiRef.current.updateRenderContext?.(); From d6ee4a262939fc285b422366678f6acad98eb787 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 23:54:01 +0100 Subject: [PATCH 023/129] fix --- .../src/hooks/features/dimensions/useGridDimensions.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index abfc545255dc0..4c5cb6dfa344f 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -163,7 +163,7 @@ export function useGridDimensions( } const rootElement = apiRef.current.rootElementRef.current; - const scrollbarSize = measureScrollbarSize(rootElement, columnsTotalWidth, props.scrollbarSize); + const scrollbarSize = measureScrollbarSize(rootElement, props.scrollbarSize); const topContainerHeight = headersTotalHeight + (rowsMeta.pinnedTopRowsTotalHeight ?? 0); const bottomContainerHeight = rowsMeta.pinnedBottomRowsTotalHeight ?? 0; @@ -377,11 +377,7 @@ export function useGridDimensions( } const scrollbarSizeCache = new WeakMap(); -function measureScrollbarSize( - rootElement: Element | null, - columnsTotalWidth: number, - scrollbarSize: number | undefined, -) { +function measureScrollbarSize(rootElement: Element | null, scrollbarSize: number | undefined) { if (scrollbarSize !== undefined) { return scrollbarSize; } From 2eab88c1eec263f56be1b3ae12b68c8dfecaac11 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 4 Dec 2024 23:57:48 +0100 Subject: [PATCH 024/129] test --- .../src/components/virtualization/GridVirtualScrollbar.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx index 07912b112ea63..37f8f5963f955 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx @@ -79,10 +79,8 @@ const GridVirtualScrollbar = React.forwardRef Date: Thu, 5 Dec 2024 00:36:20 +0100 Subject: [PATCH 025/129] fix --- .../components/virtualization/GridVirtualScrollbar.tsx | 10 +++++++--- .../features/virtualization/useGridVirtualScroller.tsx | 10 ---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx index 37f8f5963f955..2f4cfefa77c06 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx @@ -7,10 +7,11 @@ import { } from '@mui/utils'; import { useOnMount } from '../../hooks/utils/useOnMount'; import { useGridPrivateApiContext } from '../../hooks/utils/useGridPrivateApiContext'; -import { gridDimensionsSelector, useGridSelector } from '../../hooks'; +import { gridDimensionsSelector } from '../../hooks'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; +import { useGridSelector } from '../../hooks/utils/useGridSelector'; type Position = 'vertical' | 'horizontal'; type OwnerState = DataGridProcessedProps; @@ -75,12 +76,15 @@ const GridVirtualScrollbar = React.forwardRef(null); const contentRef = React.useRef(null); const classes = useUtilityClasses(rootProps, props.position); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); + const dimensions = gridDimensionsSelector(apiRef.current.state); const propertyDimension = props.position === 'vertical' ? 'height' : 'width'; const propertyScroll = props.position === 'vertical' ? 'scrollTop' : 'scrollLeft'; + const hasScroll = props.position === 'vertical' ? dimensions.hasScrollX : dimensions.hasScrollY; - const contentSize = dimensions.minimumSize[propertyDimension]; + const contentSize = + dimensions.minimumSize[propertyDimension] + (hasScroll ? dimensions.scrollbarSize : 0); + console.log(props.position, dimensions.hasScrollX, dimensions.hasScrollY, dimensions); const scrollbarSize = props.position === 'vertical' diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index b4259f2448a1a..774122f3445f5 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -605,16 +605,6 @@ export const useGridVirtualScroller = () => { apiRef.current.publishEvent('virtualScrollerContentSizeChange'); }, [apiRef, contentSize]); - useEnhancedEffect(() => { - // TODO a scroll reset should not be necessary - if (enabledForColumns) { - scrollerRef.current!.scrollLeft = 0; - } - if (enabledForRows) { - scrollerRef.current!.scrollTop = 0; - } - }, [enabledForColumns, enabledForRows, gridRootRef, scrollerRef]); - useEnhancedEffect(() => { if (listView) { scrollerRef.current!.scrollLeft = 0; From 7313c34c29b24ff0a9ed3a17d9114406be0886ae Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 00:47:02 +0100 Subject: [PATCH 026/129] fix --- .../src/components/virtualization/GridVirtualScrollbar.tsx | 2 -- .../hooks/features/virtualization/useGridVirtualScroller.tsx | 1 - 2 files changed, 3 deletions(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx index 2f4cfefa77c06..07f1252d77dfe 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx @@ -11,7 +11,6 @@ import { gridDimensionsSelector } from '../../hooks'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; -import { useGridSelector } from '../../hooks/utils/useGridSelector'; type Position = 'vertical' | 'horizontal'; type OwnerState = DataGridProcessedProps; @@ -84,7 +83,6 @@ const GridVirtualScrollbar = React.forwardRef { const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const selectedRowsLookup = useGridSelector(apiRef, selectedIdsLookupSelector); const currentPage = useGridVisibleRows(apiRef, rootProps); - const gridRootRef = apiRef.current.rootElementRef; const mainRef = apiRef.current.mainElementRef; const scrollerRef = apiRef.current.virtualScrollerRef; const scrollbarVerticalRef = apiRef.current.virtualScrollbarVerticalRef; From 52c051d6886d129bdd6fa22f30eae0b76bbb3897 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 01:12:23 +0100 Subject: [PATCH 027/129] test --- .../src/components/virtualization/GridVirtualScrollbar.tsx | 5 +++-- .../src/hooks/features/dimensions/useGridDimensions.ts | 2 +- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx index 07f1252d77dfe..ff981aefa3a3f 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx @@ -7,10 +7,11 @@ import { } from '@mui/utils'; import { useOnMount } from '../../hooks/utils/useOnMount'; import { useGridPrivateApiContext } from '../../hooks/utils/useGridPrivateApiContext'; -import { gridDimensionsSelector } from '../../hooks'; +import { gridDimensionsSelector, useGridSelector } from '../../hooks'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; +import { useGridApiContext } from '../../hooks/utils/useGridApiContext'; type Position = 'vertical' | 'horizontal'; type OwnerState = DataGridProcessedProps; @@ -75,7 +76,7 @@ const GridVirtualScrollbar = React.forwardRef(null); const contentRef = React.useRef(null); const classes = useUtilityClasses(rootProps, props.position); - const dimensions = gridDimensionsSelector(apiRef.current.state); + const dimensions = useGridSelector(apiRef, gridDimensionsSelector); const propertyDimension = props.position === 'vertical' ? 'height' : 'width'; const propertyScroll = props.position === 'vertical' ? 'scrollTop' : 'scrollLeft'; diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 4c5cb6dfa344f..d60d0756549f6 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -304,7 +304,7 @@ export function useGridDimensions( const root = apiRef.current.rootElementRef.current; useEnhancedEffect(() => { - if (!root || !dimensionsState.isReady) { + if (!root) { return; } apiRef.current.updateRenderContext?.(); diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 013b904447ee9..b561ce5dcebc4 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -98,7 +98,7 @@ export const useGridSelector = ( refs.current.selector = selector; useOnMount(() => { - return apiRef.current.store.subscribe(() => { + return apiRef.current.store.subscribe((state) => { const newState = applySelector(apiRef, refs.current.selector); if (!refs.current.equals(refs.current.state, newState)) { refs.current.state = newState; From 5cc425f78bc0bcd40fd87c5cf91214e688c50b87 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 01:13:16 +0100 Subject: [PATCH 028/129] test --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index b561ce5dcebc4..013b904447ee9 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -98,7 +98,7 @@ export const useGridSelector = ( refs.current.selector = selector; useOnMount(() => { - return apiRef.current.store.subscribe((state) => { + return apiRef.current.store.subscribe(() => { const newState = applySelector(apiRef, refs.current.selector); if (!refs.current.equals(refs.current.state, newState)) { refs.current.state = newState; From 0b1f757d2c364a68ac311331617682d94f0ee45b Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 01:14:59 +0100 Subject: [PATCH 029/129] test --- .../src/components/virtualization/GridVirtualScroller.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index c458d51de8ddd..ef5132a7ca649 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -71,7 +71,7 @@ export interface GridVirtualScrollerProps { function GridVirtualScroller(props: GridVirtualScrollerProps) { const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); + const dimensions = gridDimensionsSelector(apiRef.current.state); const { getOverlay, overlaysProps } = useGridOverlays(); const classes = useUtilityClasses(rootProps, dimensions, overlaysProps.loadingOverlayVariant); From 4514cd48197f0ebe76f7fa5b116abf8d3a9ef449 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 01:15:53 +0100 Subject: [PATCH 030/129] test --- .../src/components/virtualization/GridVirtualScrollbar.tsx | 2 +- .../src/components/virtualization/GridVirtualScroller.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx index ff981aefa3a3f..9a389292a7d13 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx @@ -76,7 +76,7 @@ const GridVirtualScrollbar = React.forwardRef(null); const contentRef = React.useRef(null); const classes = useUtilityClasses(rootProps, props.position); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); + const dimensions = gridDimensionsSelector(apiRef.current.state); const propertyDimension = props.position === 'vertical' ? 'height' : 'width'; const propertyScroll = props.position === 'vertical' ? 'scrollTop' : 'scrollLeft'; diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index ef5132a7ca649..c458d51de8ddd 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -71,7 +71,7 @@ export interface GridVirtualScrollerProps { function GridVirtualScroller(props: GridVirtualScrollerProps) { const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); - const dimensions = gridDimensionsSelector(apiRef.current.state); + const dimensions = useGridSelector(apiRef, gridDimensionsSelector); const { getOverlay, overlaysProps } = useGridOverlays(); const classes = useUtilityClasses(rootProps, dimensions, overlaysProps.loadingOverlayVariant); From b861e41bc11d17cc35ef9c3a42377e9c7de552a1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 11:20:06 +0100 Subject: [PATCH 031/129] fix selector returning stale data --- .../hooks/features/aggregation/useGridAggregation.ts | 2 +- .../components/virtualization/GridVirtualScrollbar.tsx | 3 +-- .../x-data-grid/src/hooks/utils/useGridSelector.ts | 10 +++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts index 7a98221e36e2b..2b3b01be2f3d8 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts @@ -132,7 +132,7 @@ export const useGridAggregation = ( const aggregationModel = useGridSelector(apiRef, gridAggregationModelSelector); useEnhancedEffect(checkAggregationRulesDiff, [checkAggregationRulesDiff, aggregationModel]); - useEnhancedEffect(() => { + React.useEffect(() => { if (props.aggregationModel !== undefined) { apiRef.current.setAggregationModel(props.aggregationModel); } diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx index 9a389292a7d13..ba3534bfbc79f 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollbar.tsx @@ -11,7 +11,6 @@ import { gridDimensionsSelector, useGridSelector } from '../../hooks'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; -import { useGridApiContext } from '../../hooks/utils/useGridApiContext'; type Position = 'vertical' | 'horizontal'; type OwnerState = DataGridProcessedProps; @@ -76,7 +75,7 @@ const GridVirtualScrollbar = React.forwardRef(null); const contentRef = React.useRef(null); const classes = useUtilityClasses(rootProps, props.position); - const dimensions = gridDimensionsSelector(apiRef.current.state); + const dimensions = useGridSelector(apiRef, gridDimensionsSelector); const propertyDimension = props.position === 'vertical' ? 'height' : 'width'; const propertyScroll = props.position === 'vertical' ? 'scrollTop' : 'scrollLeft'; diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 013b904447ee9..edc0caf79666f 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -1,10 +1,10 @@ import * as React from 'react'; import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare'; import { warnOnce } from '@mui/x-internals/warning'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import type { GridApiCommon } from '../../models/api/gridApiCommon'; import type { OutputSelector, OutputSelectorV8 } from '../../utils/createSelector'; import { useLazyRef } from './useLazyRef'; -import { useOnMount } from './useOnMount'; import type { GridCoreApi } from '../../models/api/gridCoreApi'; function isOutputSelector( @@ -97,7 +97,7 @@ export const useGridSelector = ( refs.current.equals = equals; refs.current.selector = selector; - useOnMount(() => { + useEnhancedEffect(() => { return apiRef.current.store.subscribe(() => { const newState = applySelector(apiRef, refs.current.selector); if (!refs.current.equals(refs.current.state, newState)) { @@ -105,7 +105,7 @@ export const useGridSelector = ( setState(newState); } }); - }); + }, [apiRef, refs]); return state; }; @@ -161,7 +161,7 @@ export const useGridSelectorV8 = ( } } - useOnMount(() => { + useEnhancedEffect(() => { return apiRef.current.store.subscribe(() => { const newState = applySelectorV8( apiRef, @@ -174,7 +174,7 @@ export const useGridSelectorV8 = ( setState(newState); } }); - }); + }, [apiRef, refs]); return state; }; From b3667086fa25f6e5ac6335b498690d9851ded039 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 13:39:17 +0100 Subject: [PATCH 032/129] test alternative rendercontext updates --- .../features/dimensions/useGridDimensions.ts | 16 +++++++++++++--- .../virtualization/useGridVirtualScroller.tsx | 13 ------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index d60d0756549f6..d726551823643 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -237,7 +237,7 @@ export function useGridDimensions( }; const newDimensions: GridDimensions = { - isReady: true, + isReady: !isFirstSizing.current, root: rootDimensionsRef.current, viewportOuterSize, viewportInnerSize, @@ -265,6 +265,10 @@ export function useGridDimensions( if (!areElementSizesEqual(newDimensions.viewportInnerSize, prevDimensions.viewportInnerSize)) { apiRef.current.publishEvent('viewportInnerSizeChange', newDimensions.viewportInnerSize); } + + if (prevDimensions.isReady) { + apiRef.current.updateRenderContext?.(); + } }, [ apiRef, setDimensions, @@ -302,12 +306,18 @@ export function useGridDimensions( } }, [apiRef, savedSize, updateDimensions]); + useEnhancedEffect(() => { + if (!dimensionsState.isReady) { + return; + } + apiRef.current.updateRenderContext?.(); + }, [apiRef, dimensionsState.isReady]); + const root = apiRef.current.rootElementRef.current; useEnhancedEffect(() => { if (!root) { return; } - apiRef.current.updateRenderContext?.(); const set = (k: string, v: string) => root.style.setProperty(k, v); set('--DataGrid-width', `${dimensionsState.viewportOuterSize.width}px`); @@ -323,7 +333,7 @@ export function useGridDimensions( set('--DataGrid-topContainerHeight', `${dimensionsState.topContainerHeight}px`); set('--DataGrid-bottomContainerHeight', `${dimensionsState.bottomContainerHeight}px`); set('--height', `${dimensionsState.rowHeight}px`); - }, [apiRef, root, dimensionsState]); + }, [root, dimensionsState]); const handleResize = React.useCallback>( (size) => { diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 146f676fa446e..7c34b28881403 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -610,19 +610,6 @@ export const useGridVirtualScroller = () => { } }, [listView, scrollerRef]); - useRunOnce(outerSize.width !== 0, () => { - const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns); - - const initialRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache); - updateRenderContext(initialRenderContext); - - apiRef.current.publishEvent('scrollPositionChange', { - top: scrollPosition.current.top, - left: scrollPosition.current.left, - renderContext: initialRenderContext, - }); - }); - apiRef.current.register('private', { updateRenderContext: forceUpdateRenderContext, }); From 9176ec0ee4a09fb6a1ce99fcd96d3b1beae59dcc Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 14:14:46 +0100 Subject: [PATCH 033/129] fix dimension->renderContext propagation --- .../features/dimensions/useGridDimensions.ts | 20 +++++++++---------- .../hooks/features/rows/useGridRowSpanning.ts | 3 ++- .../virtualization/useGridVirtualScroller.tsx | 1 - 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index d726551823643..68b3e673107e3 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -157,10 +157,6 @@ export function useGridDimensions( }, [apiRef, props.pagination, props.paginationMode, props.getRowHeight, rowHeight]); const updateDimensions = React.useCallback(() => { - // No need to calculate dimension until we have the root size - if (isFirstSizing.current) { - return; - } const rootElement = apiRef.current.rootElementRef.current; const scrollbarSize = measureScrollbarSize(rootElement, props.scrollbarSize); @@ -237,7 +233,7 @@ export function useGridDimensions( }; const newDimensions: GridDimensions = { - isReady: !isFirstSizing.current, + isReady: true, root: rootDimensionsRef.current, viewportOuterSize, viewportInnerSize, @@ -265,10 +261,6 @@ export function useGridDimensions( if (!areElementSizesEqual(newDimensions.viewportInnerSize, prevDimensions.viewportInnerSize)) { apiRef.current.publishEvent('viewportInnerSizeChange', newDimensions.viewportInnerSize); } - - if (prevDimensions.isReady) { - apiRef.current.updateRenderContext?.(); - } }, [ apiRef, setDimensions, @@ -311,7 +303,7 @@ export function useGridDimensions( return; } apiRef.current.updateRenderContext?.(); - }, [apiRef, dimensionsState.isReady]); + }, [apiRef, dimensionsState]); const root = apiRef.current.rootElementRef.current; useEnhancedEffect(() => { @@ -379,8 +371,14 @@ export function useGridDimensions( [props.autoHeight, debouncedSetSavedSize, logger], ); + const handlePaginationModelChange = React.useCallback(() => { + updateDimensions(); + // Update render context directly, since we're not immediately dependent on the dimensions + apiRef.current.updateRenderContext?.(); + }, [apiRef, updateDimensions]); + useGridApiOptionHandler(apiRef, 'sortedRowsSet', updateDimensions); - useGridApiOptionHandler(apiRef, 'paginationModelChange', updateDimensions); + useGridApiOptionHandler(apiRef, 'paginationModelChange', handlePaginationModelChange); useGridApiOptionHandler(apiRef, 'columnsChange', updateDimensions); useGridApiEventHandler(apiRef, 'resize', handleResize); useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowSpanning.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowSpanning.ts index ef9dafab23218..1555d77c646f6 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowSpanning.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowSpanning.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import useLazyRef from '@mui/utils/useLazyRef'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { GRID_DETAIL_PANEL_TOGGLE_FIELD } from '../../../internals/constants'; import { gridVisibleColumnDefinitionsSelector } from '../columns/gridColumnsSelector'; import { useGridVisibleRows } from '../../utils/useGridVisibleRows'; @@ -334,7 +335,7 @@ export const useGridRowSpanning = ( const prevRenderContext = React.useRef(renderContext); const isFirstRender = React.useRef(true); const shouldResetState = React.useRef(false); - React.useEffect(() => { + useEnhancedEffect(() => { const firstRender = isFirstRender.current; if (isFirstRender.current) { isFirstRender.current = false; diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 7c34b28881403..f31c263e3b9fd 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -12,7 +12,6 @@ import type { GridPrivateApiCommunity } from '../../../models/api/gridApiCommuni import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext'; import { useGridRootProps } from '../../utils/useGridRootProps'; import { useGridSelector } from '../../utils/useGridSelector'; -import { useRunOnce } from '../../utils/useRunOnce'; import { gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, From f29dfbce2ebe9285581481a4621445f838f0de68 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 14:54:56 +0100 Subject: [PATCH 034/129] fix aggregation cache not being initialized properly --- .../src/hooks/features/aggregation/useGridAggregation.ts | 7 +------ .../aggregation/useGridAggregationPreProcessors.tsx | 1 + 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts index 2b3b01be2f3d8..a4443c17837ed 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts @@ -3,10 +3,8 @@ import { gridColumnLookupSelector, useGridApiEventHandler, useGridApiMethod, - useGridSelector, } from '@mui/x-data-grid-pro'; import { GridStateInitializer } from '@mui/x-data-grid-pro/internals'; -import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { DataGridPremiumProcessedProps } from '../../../models/dataGridPremiumProps'; import { GridPrivateApiPremium } from '../../../models/gridApiPremium'; import { gridAggregationModelSelector } from './gridAggregationSelectors'; @@ -118,20 +116,17 @@ 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]); + useGridApiEventHandler(apiRef, 'aggregationModelChange', checkAggregationRulesDiff); useGridApiEventHandler(apiRef, 'columnsChange', checkAggregationRulesDiff); useGridApiEventHandler(apiRef, 'filteredRowsSet', applyAggregation); /** * EFFECTS */ - const aggregationModel = useGridSelector(apiRef, gridAggregationModelSelector); - useEnhancedEffect(checkAggregationRulesDiff, [checkAggregationRulesDiff, aggregationModel]); - React.useEffect(() => { if (props.aggregationModel !== undefined) { apiRef.current.setAggregationModel(props.aggregationModel); diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx index b0f1ab6933ae0..c962a378ff98d 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx @@ -66,6 +66,7 @@ export const useGridAggregationPreProcessors = ( }); rulesOnLastColumnHydration.current = aggregationRules; + apiRef.current.caches.aggregation.rulesOnLastColumnHydration = aggregationRules; return columnsState; }, From 6995ed765430a13956c45534103dbe7407b81a66 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 16:45:41 +0100 Subject: [PATCH 035/129] fix filler border top showing on first row --- packages/x-data-grid/src/components/GridRow.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/components/GridRow.tsx b/packages/x-data-grid/src/components/GridRow.tsx index df53a3c86f1db..6dbba6ddac40a 100644 --- a/packages/x-data-grid/src/components/GridRow.tsx +++ b/packages/x-data-grid/src/components/GridRow.tsx @@ -452,7 +452,9 @@ const GridRow = React.forwardRef(function GridRow( {cells}
{rightCells} - {scrollbarWidth !== 0 && 0} />} + {scrollbarWidth !== 0 && ( + 0} borderTop={!isFirstVisible} /> + )}
); }); From 4b7f5440c0c50855c6dce06a935f2276d11bed4d Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 5 Dec 2024 17:03:18 +0100 Subject: [PATCH 036/129] fix jumping autoheight --- .../src/hooks/features/dimensions/useGridDimensions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 68b3e673107e3..5938df69dd9c5 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -167,8 +167,8 @@ export function useGridDimensions( const nonPinnedColumnsTotalWidth = columnsTotalWidth - leftPinnedWidth - rightPinnedWidth; const contentSize = { - width: nonPinnedColumnsTotalWidth, - height: rowsMeta.currentPageTotalHeight, + width: roundToDecimalPlaces(nonPinnedColumnsTotalWidth, 1), + height: roundToDecimalPlaces(rowsMeta.currentPageTotalHeight, 1), }; let viewportOuterSize: ElementSize; From d4eb6966a88dac0fba9d406d2e448b57c5b5b82e Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 14:07:29 +0100 Subject: [PATCH 037/129] lint: reorder package.json --- packages/x-data-grid/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/package.json b/packages/x-data-grid/package.json index f552d92737473..ab0d6dc37105f 100644 --- a/packages/x-data-grid/package.json +++ b/packages/x-data-grid/package.json @@ -77,9 +77,9 @@ "@mui/system": "^5.16.14", "@mui/types": "^7.2.20", "@types/prop-types": "^15.7.14", + "@types/use-sync-external-store": "^0.0.6", "react": "^19.0.0", "react-dom": "^19.0.0", - "@types/use-sync-external-store": "^0.0.6", "rimraf": "^6.0.1" }, "engines": { From 35cf5e37992e4e6e11a9acaede37dd9619faeb11 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 14:18:06 +0100 Subject: [PATCH 038/129] remove `calculatePinnedRowsHeight` --- .../features/dimensions/useGridDimensions.ts | 4 ++-- .../src/hooks/features/rows/gridRowsUtils.ts | 20 ------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index c95998c9affb1..dc97576067882 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -4,8 +4,8 @@ import { unstable_ownerDocument as ownerDocument, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback, + unstable_debounce as debounce, } from '@mui/utils'; -import { throttle } from '@mui/x-internals/throttle'; import { GridEventListener } from '../../../models/events'; import { ElementSize } from '../../../models'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; @@ -118,7 +118,7 @@ export function useGridDimensions(apiRef: RefObject, pr const [savedSize, setSavedSize] = React.useState(); const debouncedSetSavedSize = React.useMemo( - () => throttle(setSavedSize, props.resizeThrottleMs), + () => debounce(setSavedSize, props.resizeThrottleMs), [props.resizeThrottleMs], ); React.useEffect(() => debouncedSetSavedSize.clear, [debouncedSetSavedSize]); diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts index 029d03048b6f7..09c9d5e5a2bd8 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts @@ -369,26 +369,6 @@ export const updateCacheWithNewRows = ({ }; }; -export function calculatePinnedRowsHeight(apiRef: RefObject) { - const pinnedRows = gridPinnedRowsSelector(apiRef); - const topPinnedRowsHeight = - pinnedRows?.top?.reduce((acc, value) => { - acc += apiRef.current.unstable_getRowHeight(value.id); - return acc; - }, 0) || 0; - - const bottomPinnedRowsHeight = - pinnedRows?.bottom?.reduce((acc, value) => { - acc += apiRef.current.unstable_getRowHeight(value.id); - return acc; - }, 0) || 0; - - return { - top: topPinnedRowsHeight, - bottom: bottomPinnedRowsHeight, - }; -} - export const minimalContentHeight = 'var(--DataGrid-overlayHeight, calc(var(--height) * 2))'; export function computeRowsUpdates( From 631c6b6ed6de3c8e0e4bd7baf8d9855894b3f16a Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 14:19:13 +0100 Subject: [PATCH 039/129] revert to throttle --- .../src/hooks/features/dimensions/useGridDimensions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index dc97576067882..c95998c9affb1 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -4,8 +4,8 @@ import { unstable_ownerDocument as ownerDocument, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback, - unstable_debounce as debounce, } from '@mui/utils'; +import { throttle } from '@mui/x-internals/throttle'; import { GridEventListener } from '../../../models/events'; import { ElementSize } from '../../../models'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; @@ -118,7 +118,7 @@ export function useGridDimensions(apiRef: RefObject, pr const [savedSize, setSavedSize] = React.useState(); const debouncedSetSavedSize = React.useMemo( - () => debounce(setSavedSize, props.resizeThrottleMs), + () => throttle(setSavedSize, props.resizeThrottleMs), [props.resizeThrottleMs], ); React.useEffect(() => debouncedSetSavedSize.clear, [debouncedSetSavedSize]); From 2ee5a2806c578a33fb566faa61c6075655a11e68 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 14:38:42 +0100 Subject: [PATCH 040/129] fix test --- packages/x-data-grid/src/tests/layout.DataGrid.test.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index 94b0c0493a625..596e665a38b3d 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1261,10 +1261,11 @@ describe(' - Layout & warnings', () => { /> , ); - }).toErrorDev([ - 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', - 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', - ]); + }).toErrorDev( + Array(4).fill([ + 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', + ]), + ); }, ); From 8bb087e73508abd19907ad296761196c6bc88d38 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 15:01:37 +0100 Subject: [PATCH 041/129] oops --- packages/x-data-grid/src/tests/layout.DataGrid.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index 596e665a38b3d..5c58a5384c53b 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1262,9 +1262,9 @@ describe(' - Layout & warnings', () => { , ); }).toErrorDev( - Array(4).fill([ + Array(4).fill( 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', - ]), + ), ); }, ); From 30c10ba41cf779c6b3aa591af31a0c152522fbcd Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 15:52:01 +0100 Subject: [PATCH 042/129] fix --- packages/x-data-grid/src/tests/layout.DataGrid.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index 5c58a5384c53b..d291b460750df 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1262,7 +1262,7 @@ describe(' - Layout & warnings', () => { , ); }).toErrorDev( - Array(4).fill( + Array(3).fill( 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', ), ); From 14c42f4017f324699ba81d694a39134f844412d8 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 17:18:43 +0100 Subject: [PATCH 043/129] control update flow --- .../hooks/features/dimensions/useGridDimensions.ts | 12 +++++------- .../virtualization/useGridVirtualScroller.tsx | 10 +++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index c95998c9affb1..0aa72cadb3184 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -157,6 +157,9 @@ export function useGridDimensions(apiRef: RefObject, pr }, [apiRef, props.pagination, props.paginationMode, props.getRowHeight, rowHeight]); const updateDimensions = React.useCallback(() => { + if (isFirstSizing.current) { + return; + } // All the floating point dimensions should be rounded to .1 decimal places to avoid subpixel rendering issues // https://github.com/mui/mui-x/issues/9550#issuecomment-1619020477 // https://github.com/mui/mui-x/issues/15721 @@ -262,6 +265,8 @@ export function useGridDimensions(apiRef: RefObject, pr if (!areElementSizesEqual(newDimensions.viewportInnerSize, prevDimensions.viewportInnerSize)) { apiRef.current.publishEvent('viewportInnerSizeChange', newDimensions.viewportInnerSize); } + + apiRef.current.updateRenderContext?.(); }, [ apiRef, setDimensions, @@ -299,13 +304,6 @@ export function useGridDimensions(apiRef: RefObject, pr } }, [apiRef, savedSize, updateDimensions]); - useEnhancedEffect(() => { - if (!dimensionsState.isReady) { - return; - } - apiRef.current.updateRenderContext?.(); - }, [apiRef, dimensionsState]); - const root = apiRef.current.rootElementRef.current; useEnhancedEffect(() => { if (!root) { diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 3fc3462ff4adb..2069fba06cb26 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -245,17 +245,14 @@ export const useGridVirtualScroller = () => { }; }); - // The lazy-loading hook is listening to `renderedRowsIntervalChange`, - // but only does something if the dimensions are also available. - // So we wait until we have valid dimensions before publishing the first event. - if (dimensions.isReady && didRowsIntervalChange) { + if (didRowsIntervalChange) { previousRowContext.current = nextRenderContext; apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext); } previousContextScrollPosition.current = scrollPosition.current; }, - [apiRef, dimensions.isReady], + [apiRef], ); const triggerUpdateRenderContext = useEventCallback(() => { @@ -335,6 +332,9 @@ export const useGridVirtualScroller = () => { }); const forceUpdateRenderContext = () => { + if (!gridDimensionsSelector(apiRef.current.state).isReady) { + return; + } const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns); const nextRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache); // Reset the frozen context when the render context changes, see the illustration in https://github.com/mui/mui-x/pull/12353 From 989811c43eb72c28a39aea915e0d154533395d73 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 17:20:22 +0100 Subject: [PATCH 044/129] refactor --- .../src/hooks/features/dimensions/useGridDimensions.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 0aa72cadb3184..d8c0fd3d1aa1b 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -366,14 +366,8 @@ export function useGridDimensions(apiRef: RefObject, pr [props.autoHeight, debouncedSetSavedSize, logger], ); - const handlePaginationModelChange = React.useCallback(() => { - updateDimensions(); - // Update render context directly, since we're not immediately dependent on the dimensions - apiRef.current.updateRenderContext?.(); - }, [apiRef, updateDimensions]); - useGridApiOptionHandler(apiRef, 'sortedRowsSet', updateDimensions); - useGridApiOptionHandler(apiRef, 'paginationModelChange', handlePaginationModelChange); + useGridApiOptionHandler(apiRef, 'paginationModelChange', updateDimensions); useGridApiOptionHandler(apiRef, 'columnsChange', updateDimensions); useGridApiEventHandler(apiRef, 'resize', handleResize); useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); From 0a91c02cf2b5a399135e15b5721bc90ef98b8cdc Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 17:43:40 +0100 Subject: [PATCH 045/129] fix renderedRowsIntervalChange --- .../features/virtualization/useGridVirtualScroller.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 2069fba06cb26..9220b2a955ea0 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -246,8 +246,14 @@ export const useGridVirtualScroller = () => { }); if (didRowsIntervalChange) { + const isInitialRender = previousRowContext.current === EMPTY_RENDER_CONTEXT; + // The lazy-loading hook is listening to `renderedRowsIntervalChange`, + // but only does something if we already have a render context, because + // otherwise we would call an update directly on mount + if (!isInitialRender) { + apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext); + } previousRowContext.current = nextRenderContext; - apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext); } previousContextScrollPosition.current = scrollPosition.current; From c19f001b0acc3a6153c4889429813a7c44da407c Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 18:03:48 +0100 Subject: [PATCH 046/129] fix --- .../virtualization/useGridVirtualScroller.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 9220b2a955ea0..7d8bc6c7c5327 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -245,15 +245,13 @@ export const useGridVirtualScroller = () => { }; }); - if (didRowsIntervalChange) { - const isInitialRender = previousRowContext.current === EMPTY_RENDER_CONTEXT; - // The lazy-loading hook is listening to `renderedRowsIntervalChange`, - // but only does something if we already have a render context, because - // otherwise we would call an update directly on mount - if (!isInitialRender) { - apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext); - } + // The lazy-loading hook is listening to `renderedRowsIntervalChange`, + // but only does something if we already have a render context, because + // otherwise we would call an update directly on mount + const isReady = gridDimensionsSelector(apiRef.current.state).isReady; + if (isReady && didRowsIntervalChange) { previousRowContext.current = nextRenderContext; + apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext); } previousContextScrollPosition.current = scrollPosition.current; From f88d9a2fdc6de24d24eec63d34f162a133e4a006 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 18:12:58 +0100 Subject: [PATCH 047/129] fix --- .../virtualization/useGridVirtualScroller.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 7d8bc6c7c5327..ec1f476510003 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -336,7 +336,7 @@ export const useGridVirtualScroller = () => { }); const forceUpdateRenderContext = () => { - if (!gridDimensionsSelector(apiRef.current.state).isReady) { + if (!gridDimensionsSelector(apiRef.current.state).isReady || !isRenderContextReady.current) { return; } const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns); @@ -626,6 +626,17 @@ export const useGridVirtualScroller = () => { }, [listView, scrollerRef]); useRunOnce(outerSize.width !== 0, () => { + const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns); + + const initialRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache); + updateRenderContext(initialRenderContext); + + apiRef.current.publishEvent('scrollPositionChange', { + top: scrollPosition.current.top, + left: scrollPosition.current.left, + renderContext: initialRenderContext, + }); + isRenderContextReady.current = true; if (rootProps.initialState?.scroll && scrollerRef.current) { From 0ecb2dd7f26d2fb04d7c03845ce153133ecd0c4c Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 18:30:08 +0100 Subject: [PATCH 048/129] test --- .../hooks/features/virtualization/useGridVirtualScroller.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index ec1f476510003..4c9d48d4dfa77 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -336,7 +336,7 @@ export const useGridVirtualScroller = () => { }); const forceUpdateRenderContext = () => { - if (!gridDimensionsSelector(apiRef.current.state).isReady || !isRenderContextReady.current) { + if (!gridDimensionsSelector(apiRef.current.state).isReady) { return; } const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns); From 73d0ff736f27be446dfbd3453e7fff0e0e2d21bc Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 20:55:21 +0100 Subject: [PATCH 049/129] properly initialize static dimensions --- .../useDataGridPremiumComponent.tsx | 2 +- .../DataGridPro/useDataGridProComponent.tsx | 2 +- .../src/DataGrid/useDataGridComponent.tsx | 2 +- .../features/dimensions/useGridDimensions.ts | 88 ++++++++++++++----- .../virtualization/useGridVirtualScroller.tsx | 7 +- 5 files changed, 69 insertions(+), 32 deletions(-) diff --git a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx index 375dd735943ac..69fcd83148640 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx +++ b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx @@ -122,7 +122,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); @@ -149,6 +148,7 @@ export const useDataGridPremiumComponent = ( useGridInitializeState(virtualizationStateInitializer, apiRef, props); useGridInitializeState(dataSourceStateInitializer, apiRef, props); useGridInitializeState(listViewStateInitializer, apiRef, props); + useGridInitializeState(dimensionsStateInitializer, apiRef, props); useGridRowGrouping(apiRef, props); useGridHeaderFiltering(apiRef, props); diff --git a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx index 1f66716fdb3f0..56f7239c569b3 100644 --- a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx +++ b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx @@ -110,7 +110,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); @@ -134,6 +133,7 @@ export const useDataGridProComponent = ( useGridInitializeState(virtualizationStateInitializer, apiRef, props); useGridInitializeState(dataSourceStateInitializer, apiRef, props); useGridInitializeState(listViewStateInitializer, apiRef, props); + useGridInitializeState(dimensionsStateInitializer, apiRef, props); useGridHeaderFiltering(apiRef, props); useGridTreeData(apiRef, props); diff --git a/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx b/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx index 6787227972e22..a1bacc7565581 100644 --- a/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx +++ b/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx @@ -81,7 +81,6 @@ export const useDataGridComponent = ( /** * Register all state initializers here. */ - useGridInitializeState(dimensionsStateInitializer, apiRef, props); useGridInitializeState(rowSelectionStateInitializer, apiRef, props); useGridInitializeState(columnsStateInitializer, apiRef, props); useGridInitializeState(paginationStateInitializer, apiRef, props); @@ -99,6 +98,7 @@ export const useDataGridComponent = ( useGridInitializeState(columnGroupsStateInitializer, apiRef, props); useGridInitializeState(virtualizationStateInitializer, apiRef, props); useGridInitializeState(listViewStateInitializer, apiRef, props); + useGridInitializeState(dimensionsStateInitializer, apiRef, props); useGridKeyboardNavigation(apiRef, props); useGridRowSelection(apiRef, props); diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index d8c0fd3d1aa1b..f46459c28cdf3 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -75,12 +75,65 @@ const EMPTY_DIMENSIONS: GridDimensions = { bottomContainerHeight: 0, }; -export const dimensionsStateInitializer: GridStateInitializer = (state) => { +const getStaticDimensions = ( + props: RootProps, + apiRef: RefObject, + density: number, + pinnedColumnns: ReturnType, +) => { + const validRowHeight = getValidRowHeight( + props.rowHeight, + DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, + rowHeightWarning, + ); + + return { + rowHeight: Math.floor(validRowHeight * density), + headerHeight: Math.floor(props.columnHeaderHeight * density), + groupHeaderHeight: Math.floor( + (props.columnGroupHeaderHeight ?? props.columnHeaderHeight) * density, + ), + headerFilterHeight: Math.floor( + (props.headerFilterHeight ?? props.columnHeaderHeight) * density, + ), + columnsTotalWidth: roundToDecimalPlaces(gridColumnsTotalWidthSelector(apiRef), 1), + headersTotalHeight: getTotalHeaderHeight(apiRef, props), + leftPinnedWidth: gridVisiblePinnedColumnDefinitionsSelector(apiRef).left.reduce( + (w, col) => w + col.computedWidth, + 0, + ), + rightPinnedWidth: gridVisiblePinnedColumnDefinitionsSelector(apiRef).right.reduce( + (w, col) => w + col.computedWidth, + 0, + ), + }; +}; + +export const dimensionsStateInitializer: GridStateInitializer = ( + state, + props, + apiRef, +) => { const dimensions = EMPTY_DIMENSIONS; + const density = gridDensityFactorSelector(apiRef); + const validRowHeight = getValidRowHeight( + props.rowHeight, + DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, + rowHeightWarning, + ); + return { ...state, - dimensions, + dimensions: { + ...dimensions, + ...getStaticDimensions( + props, + apiRef, + density, + gridVisiblePinnedColumnDefinitionsSelector(apiRef), + ), + }, }; }; @@ -93,28 +146,17 @@ export function useGridDimensions(apiRef: RefObject, pr const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); const isFirstSizing = React.useRef(true); - const validRowHeight = React.useMemo( - () => - getValidRowHeight( - props.rowHeight, - DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, - rowHeightWarning, - ), - [props.rowHeight], - ); - const rowHeight = Math.floor(validRowHeight * densityFactor); - const headerHeight = Math.floor(props.columnHeaderHeight * densityFactor); - const groupHeaderHeight = Math.floor( - (props.columnGroupHeaderHeight ?? props.columnHeaderHeight) * densityFactor, - ); - const headerFilterHeight = Math.floor( - (props.headerFilterHeight ?? props.columnHeaderHeight) * densityFactor, - ); - const columnsTotalWidth = roundToDecimalPlaces(gridColumnsTotalWidthSelector(apiRef), 1); - const headersTotalHeight = getTotalHeaderHeight(apiRef, props); - const leftPinnedWidth = pinnedColumns.left.reduce((w, col) => w + col.computedWidth, 0); - const rightPinnedWidth = pinnedColumns.right.reduce((w, col) => w + col.computedWidth, 0); + const { + rowHeight, + headerHeight, + groupHeaderHeight, + headerFilterHeight, + columnsTotalWidth, + headersTotalHeight, + leftPinnedWidth, + rightPinnedWidth, + } = getStaticDimensions(props, apiRef, densityFactor, pinnedColumns); const [savedSize, setSavedSize] = React.useState(); const debouncedSetSavedSize = React.useMemo( diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 4c9d48d4dfa77..1e78fc686eb82 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -626,15 +626,10 @@ export const useGridVirtualScroller = () => { }, [listView, scrollerRef]); useRunOnce(outerSize.width !== 0, () => { - const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns); - - const initialRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache); - updateRenderContext(initialRenderContext); - apiRef.current.publishEvent('scrollPositionChange', { top: scrollPosition.current.top, left: scrollPosition.current.left, - renderContext: initialRenderContext, + renderContext: gridRenderContextSelector(apiRef.current.state), }); isRenderContextReady.current = true; From 6201f0230b800d6cf520a41e35c42efc14465213 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 21:01:12 +0100 Subject: [PATCH 050/129] fix order --- .../src/DataGridPremium/useDataGridPremiumComponent.tsx | 2 +- .../x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx | 2 +- packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx index 69fcd83148640..bbec2c95718a8 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx +++ b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx @@ -147,8 +147,8 @@ export const useDataGridPremiumComponent = ( useGridInitializeState(columnGroupsStateInitializer, apiRef, props); useGridInitializeState(virtualizationStateInitializer, apiRef, props); useGridInitializeState(dataSourceStateInitializer, apiRef, props); - useGridInitializeState(listViewStateInitializer, apiRef, props); useGridInitializeState(dimensionsStateInitializer, apiRef, props); + useGridInitializeState(listViewStateInitializer, apiRef, props); useGridRowGrouping(apiRef, props); useGridHeaderFiltering(apiRef, props); diff --git a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx index 56f7239c569b3..209c2e3dbb885 100644 --- a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx +++ b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx @@ -132,8 +132,8 @@ export const useDataGridProComponent = ( useGridInitializeState(columnGroupsStateInitializer, apiRef, props); useGridInitializeState(virtualizationStateInitializer, apiRef, props); useGridInitializeState(dataSourceStateInitializer, apiRef, props); - useGridInitializeState(listViewStateInitializer, apiRef, props); useGridInitializeState(dimensionsStateInitializer, apiRef, props); + useGridInitializeState(listViewStateInitializer, apiRef, props); useGridHeaderFiltering(apiRef, props); useGridTreeData(apiRef, props); diff --git a/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx b/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx index a1bacc7565581..e74a9ca9fd30a 100644 --- a/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx +++ b/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx @@ -97,8 +97,8 @@ export const useDataGridComponent = ( useGridInitializeState(columnMenuStateInitializer, apiRef, props); useGridInitializeState(columnGroupsStateInitializer, apiRef, props); useGridInitializeState(virtualizationStateInitializer, apiRef, props); - useGridInitializeState(listViewStateInitializer, apiRef, props); useGridInitializeState(dimensionsStateInitializer, apiRef, props); + useGridInitializeState(listViewStateInitializer, apiRef, props); useGridKeyboardNavigation(apiRef, props); useGridRowSelection(apiRef, props); From c4190fb07fdea1f62d14ef0b1806b69571fb7f80 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 21:05:36 +0100 Subject: [PATCH 051/129] fix --- .../src/hooks/features/dimensions/useGridDimensions.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index f46459c28cdf3..b58fcb2423b52 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -98,14 +98,8 @@ const getStaticDimensions = ( ), columnsTotalWidth: roundToDecimalPlaces(gridColumnsTotalWidthSelector(apiRef), 1), headersTotalHeight: getTotalHeaderHeight(apiRef, props), - leftPinnedWidth: gridVisiblePinnedColumnDefinitionsSelector(apiRef).left.reduce( - (w, col) => w + col.computedWidth, - 0, - ), - rightPinnedWidth: gridVisiblePinnedColumnDefinitionsSelector(apiRef).right.reduce( - (w, col) => w + col.computedWidth, - 0, - ), + leftPinnedWidth: pinnedColumnns.left.reduce((w, col) => w + col.computedWidth, 0), + rightPinnedWidth: pinnedColumnns.right.reduce((w, col) => w + col.computedWidth, 0), }; }; From 9f5a7098c78dcd6c75713f6f269a1233972020e2 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 26 Jan 2025 22:27:21 +0100 Subject: [PATCH 052/129] cleanup --- .../src/hooks/features/dimensions/useGridDimensions.ts | 5 ----- .../features/virtualization/useGridVirtualScroller.tsx | 10 +++++++--- .../x-data-grid/src/tests/layout.DataGrid.test.tsx | 9 ++++----- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index b58fcb2423b52..1961c033aa8bf 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -111,11 +111,6 @@ export const dimensionsStateInitializer: GridStateInitializer = ( const dimensions = EMPTY_DIMENSIONS; const density = gridDensityFactorSelector(apiRef); - const validRowHeight = getValidRowHeight( - props.rowHeight, - DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, - rowHeightWarning, - ); return { ...state, diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 1e78fc686eb82..74df1991a03b8 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -336,7 +336,11 @@ export const useGridVirtualScroller = () => { }); const forceUpdateRenderContext = () => { - if (!gridDimensionsSelector(apiRef.current.state).isReady) { + // skip update if dimensions are not ready and virtualization is enabled + if ( + !gridDimensionsSelector(apiRef.current.state).isReady && + (enabledForRows || enabledForColumns) + ) { return; } const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns); @@ -625,11 +629,11 @@ export const useGridVirtualScroller = () => { } }, [listView, scrollerRef]); - useRunOnce(outerSize.width !== 0, () => { + useRunOnce(renderContext !== EMPTY_RENDER_CONTEXT, () => { apiRef.current.publishEvent('scrollPositionChange', { top: scrollPosition.current.top, left: scrollPosition.current.left, - renderContext: gridRenderContextSelector(apiRef.current.state), + renderContext, }); isRenderContextReady.current = true; diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index d291b460750df..94b0c0493a625 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1261,11 +1261,10 @@ describe(' - Layout & warnings', () => { /> , ); - }).toErrorDev( - Array(3).fill( - 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', - ), - ); + }).toErrorDev([ + 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', + 'Encountered two children with the same key, `id`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.', + ]); }, ); From 051db9cd082dd909502046312a0951801e941f49 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 00:25:04 +0100 Subject: [PATCH 053/129] split ownership of renderContext updates between `useGridDimensions` and `useGridVirtualScroller` --- .../useDataGridPremiumComponent.tsx | 2 +- .../DataGridPro/useDataGridProComponent.tsx | 2 +- .../src/DataGrid/useDataGridComponent.tsx | 2 +- .../features/dimensions/useGridDimensions.ts | 32 +++++++++++++++---- .../hooks/features/rows/useGridRowsMeta.ts | 14 ++++++-- .../virtualization/useGridVirtualScroller.tsx | 9 +++--- 6 files changed, 44 insertions(+), 17 deletions(-) diff --git a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx index bbec2c95718a8..0e85aee52455b 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx +++ b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx @@ -142,12 +142,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); diff --git a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx index 209c2e3dbb885..ba47b0ac8fd69 100644 --- a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx +++ b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx @@ -127,12 +127,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); diff --git a/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx b/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx index e74a9ca9fd30a..57b087ab0ee9d 100644 --- a/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx +++ b/packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx @@ -93,11 +93,11 @@ export const useDataGridComponent = ( useGridInitializeState(rowSpanningStateInitializer, apiRef, props); useGridInitializeState(densityStateInitializer, apiRef, props); useGridInitializeState(columnResizeStateInitializer, apiRef, props); - useGridInitializeState(rowsMetaStateInitializer, apiRef, props); useGridInitializeState(columnMenuStateInitializer, apiRef, props); useGridInitializeState(columnGroupsStateInitializer, apiRef, props); useGridInitializeState(virtualizationStateInitializer, apiRef, props); useGridInitializeState(dimensionsStateInitializer, apiRef, props); + useGridInitializeState(rowsMetaStateInitializer, apiRef, props); useGridInitializeState(listViewStateInitializer, apiRef, props); useGridKeyboardNavigation(apiRef, props); diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 1961c033aa8bf..e305f3a3bdabb 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -33,6 +33,7 @@ import { GridStateInitializer } from '../../utils/useGridInitializeState'; import { DATA_GRID_PROPS_DEFAULT_VALUES } from '../../../constants/dataGridPropsDefaultValues'; import { roundToDecimalPlaces } from '../../../utils/roundToDecimalPlaces'; import { isJSDOM } from '../../../utils/isJSDOM'; +import { isDeepEqual } from '../../../utils/utils'; type RootProps = Pick< DataGridProcessedProps, @@ -291,6 +292,11 @@ export function useGridDimensions(apiRef: RefObject, pr }; const prevDimensions = apiRef.current.state.dimensions; + + if (isDeepEqual(prevDimensions as any, newDimensions)) { + return; + } + setDimensions(newDimensions); if (!areElementSizesEqual(newDimensions.viewportInnerSize, prevDimensions.viewportInnerSize)) { @@ -329,7 +335,7 @@ export function useGridDimensions(apiRef: RefObject, pr useGridApiMethod(apiRef, apiPrivate, 'private'); useEnhancedEffect(() => { - if (savedSize) { + if (!isFirstSizing.current) { updateDimensions(); apiRef.current.publishEvent('debouncedResize', rootDimensionsRef.current!); } @@ -355,7 +361,22 @@ export function useGridDimensions(apiRef: RefObject, pr set('--DataGrid-topContainerHeight', `${dimensionsState.topContainerHeight}px`); set('--DataGrid-bottomContainerHeight', `${dimensionsState.bottomContainerHeight}px`); set('--height', `${dimensionsState.rowHeight}px`); - }, [root, dimensionsState]); + }, [ + root, + dimensionsState.viewportOuterSize.width, + dimensionsState.hasScrollX, + dimensionsState.hasScrollY, + dimensionsState.scrollbarSize, + dimensionsState.rowWidth, + dimensionsState.columnsTotalWidth, + dimensionsState.leftPinnedWidth, + dimensionsState.rightPinnedWidth, + dimensionsState.headerHeight, + dimensionsState.headersTotalHeight, + dimensionsState.topContainerHeight, + dimensionsState.bottomContainerHeight, + dimensionsState.rowHeight, + ]); const handleResize = React.useCallback>( (size) => { @@ -387,19 +408,16 @@ export function useGridDimensions(apiRef: RefObject, pr if (isFirstSizing.current) { // We want to initialize the grid dimensions as soon as possible to avoid flickering - setSavedSize(size); isFirstSizing.current = false; + updateDimensions(); return; } debouncedSetSavedSize(size); }, - [props.autoHeight, debouncedSetSavedSize, logger], + [updateDimensions, props.autoHeight, debouncedSetSavedSize, logger], ); - useGridApiOptionHandler(apiRef, 'sortedRowsSet', updateDimensions); - useGridApiOptionHandler(apiRef, 'paginationModelChange', updateDimensions); - useGridApiOptionHandler(apiRef, 'columnsChange', updateDimensions); useGridApiEventHandler(apiRef, 'resize', handleResize); useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); } diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 092231dce0b6a..14ef77612145a 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -17,7 +17,7 @@ import { gridPaginationSelector } from '../pagination/gridPaginationSelector'; import { gridSortModelSelector } from '../sorting/gridSortingSelector'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; -import { gridPinnedRowsSelector } from './gridRowsSelector'; +import { gridPinnedRowsSelector, gridRowCountSelector } from './gridRowsSelector'; import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; import { getValidRowHeight, getRowHeightWarning } from './gridRowsUtils'; import type { HeightEntry } from './gridRowsMetaInterfaces'; @@ -29,11 +29,19 @@ export const rowsMetaStateInitializer: GridStateInitializer = (state, props, api heights: new Map(), }; + const baseRowHeight = gridDimensionsSelector(apiRef.current.state).rowHeight; + const dataRowCount = gridRowCountSelector(apiRef.current.state); + const pagination = gridPaginationSelector(apiRef.current.state); + const rowCount = Math.min( + pagination.enabled ? pagination.paginationModel.pageSize : dataRowCount, + dataRowCount, + ); + return { ...state, rowsMeta: { - currentPageTotalHeight: 0, - positions: [], + currentPageTotalHeight: rowCount * baseRowHeight, + positions: Array.from({ length: rowCount }, (_, i) => i * baseRowHeight), pinnedTopRowsTotalHeight: 0, pinnedBottomRowsTotalHeight: 0, }, diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 74df1991a03b8..a127bdff576b0 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -24,7 +24,7 @@ import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; import { gridPinnedRowsSelector } from '../rows/gridRowsSelector'; import { GridPinnedRowsPosition } from '../rows/gridRowsInterfaces'; import { useGridVisibleRows, getVisibleRows } from '../../utils/useGridVisibleRows'; -import { useGridApiEventHandler } from '../../utils'; +import { useGridApiOptionHandler } from '../../utils'; import * as platform from '../../../utils/platform'; import { clamp, range } from '../../../utils/utils'; import { @@ -692,9 +692,10 @@ export const useGridVirtualScroller = () => { updateRenderContext: forceUpdateRenderContext, }); - useGridApiEventHandler(apiRef, 'columnsChange', forceUpdateRenderContext); - useGridApiEventHandler(apiRef, 'filteredRowsSet', forceUpdateRenderContext); - useGridApiEventHandler(apiRef, 'rowExpansionChange', forceUpdateRenderContext); + useGridApiOptionHandler(apiRef, 'sortedRowsSet', forceUpdateRenderContext); + useGridApiOptionHandler(apiRef, 'paginationModelChange', forceUpdateRenderContext); + useGridApiOptionHandler(apiRef, 'columnsChange', forceUpdateRenderContext); + useGridApiOptionHandler(apiRef, 'rowExpansionChange', forceUpdateRenderContext); return { renderContext, From 666bf4c03b12c6ba5fbf0d24a50ec8f977fc4d8d Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 00:26:09 +0100 Subject: [PATCH 054/129] remove unnecessary event handler --- .../src/hooks/features/virtualization/useGridVirtualScroller.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index a127bdff576b0..aad121bf44615 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -695,7 +695,6 @@ export const useGridVirtualScroller = () => { useGridApiOptionHandler(apiRef, 'sortedRowsSet', forceUpdateRenderContext); useGridApiOptionHandler(apiRef, 'paginationModelChange', forceUpdateRenderContext); useGridApiOptionHandler(apiRef, 'columnsChange', forceUpdateRenderContext); - useGridApiOptionHandler(apiRef, 'rowExpansionChange', forceUpdateRenderContext); return { renderContext, From 94a1caf1b2f94c20180f577a5b59d2275bac38df Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 00:50:40 +0100 Subject: [PATCH 055/129] fix flaky test --- .../src/tests/dataSourceAggregation.DataGridPremium.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx index f7065916f2363..d3bb2fb2d2a56 100644 --- a/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/dataSourceAggregation.DataGridPremium.test.tsx @@ -102,6 +102,7 @@ describe(' - Data source aggregation', () => { await waitFor(() => { expect(getRowsSpy.callCount).to.be.greaterThan(0); }); + await getRowsSpy.lastCall.returnValue; await user.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); expect(screen.queryByLabelText('Aggregation')).not.to.equal(null); }); From b72df725591990b65e325211d24f28da7e6a420b Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 10:38:58 +0100 Subject: [PATCH 056/129] remove ! --- .../src/hooks/features/dimensions/useGridDimensions.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index e305f3a3bdabb..3148c9a10b1e4 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -428,15 +428,15 @@ function measureScrollbarSize(rootElement: Element | null, scrollbarSize: number return scrollbarSize; } - const cachedSize = scrollbarSizeCache.get(rootElement!); - if (cachedSize !== undefined) { - return cachedSize; - } - if (rootElement === null) { return 0; } + const cachedSize = scrollbarSizeCache.get(rootElement); + if (cachedSize !== undefined) { + return cachedSize; + } + const doc = ownerDocument(rootElement); const scrollDiv = doc.createElement('div'); scrollDiv.style.width = '99px'; From 5b8686d9414e34a7cee1e4c6a54094cd19f1caff Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 10:49:02 +0100 Subject: [PATCH 057/129] deprecate forceupdate --- .../src/hooks/core/useGridStateInitialization.ts | 6 +++--- packages/x-data-grid/src/models/api/gridStateApi.ts | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts b/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts index 63cabbe5aa168..1cffa00a4e7b2 100644 --- a/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts +++ b/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts @@ -12,8 +12,6 @@ export const useGridStateInitialization = > >({}); - const [, rawForceUpdate] = React.useState(); - const registerControlState = React.useCallback< GridStatePrivateApi['registerControlState'] >((controlStateItem) => { @@ -118,7 +116,9 @@ export const useGridStateInitialization = rawForceUpdate(() => apiRef.current.state), [apiRef]); + const forceUpdate = React.useCallback(() => { + // @deprecated - do nothing + }, [apiRef]); const publicStateApi: Omit, 'state'> = { setState, diff --git a/packages/x-data-grid/src/models/api/gridStateApi.ts b/packages/x-data-grid/src/models/api/gridStateApi.ts index a1c88c022edec..f0b60a0ce59e9 100644 --- a/packages/x-data-grid/src/models/api/gridStateApi.ts +++ b/packages/x-data-grid/src/models/api/gridStateApi.ts @@ -9,6 +9,7 @@ export interface GridStateApi { state: State; /** * Forces the grid to rerender. It's often used after a state update. + * @deprecated - no longer needed. */ forceUpdate: () => void; /** From 68e79dfa3d1b99408f1cbecc9bfbb8864b613ad1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 10:51:57 +0100 Subject: [PATCH 058/129] typo --- packages/x-data-grid/src/models/api/gridStateApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/models/api/gridStateApi.ts b/packages/x-data-grid/src/models/api/gridStateApi.ts index f0b60a0ce59e9..40a0cc98e7659 100644 --- a/packages/x-data-grid/src/models/api/gridStateApi.ts +++ b/packages/x-data-grid/src/models/api/gridStateApi.ts @@ -9,7 +9,7 @@ export interface GridStateApi { state: State; /** * Forces the grid to rerender. It's often used after a state update. - * @deprecated - no longer needed. + * @deprecated no longer needed. */ forceUpdate: () => void; /** From 663a5ddda54a79b63817ed4a66a6aac280aa3ed8 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 11:08:06 +0100 Subject: [PATCH 059/129] lint --- .../x-data-grid/src/hooks/core/useGridStateInitialization.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts b/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts index 1cffa00a4e7b2..cdf14bbf6c33f 100644 --- a/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts +++ b/packages/x-data-grid/src/hooks/core/useGridStateInitialization.ts @@ -118,7 +118,7 @@ export const useGridStateInitialization = { // @deprecated - do nothing - }, [apiRef]); + }, []); const publicStateApi: Omit, 'state'> = { setState, From 7a93d2eafde67e4936470e4775b8480d2df2836f Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 12:04:22 +0100 Subject: [PATCH 060/129] remove unused prop --- packages/x-data-grid/src/components/GridRow.tsx | 3 --- .../hooks/features/virtualization/useGridVirtualScroller.tsx | 2 -- 2 files changed, 5 deletions(-) diff --git a/packages/x-data-grid/src/components/GridRow.tsx b/packages/x-data-grid/src/components/GridRow.tsx index d311c410047e4..4c3d05590585f 100644 --- a/packages/x-data-grid/src/components/GridRow.tsx +++ b/packages/x-data-grid/src/components/GridRow.tsx @@ -56,7 +56,6 @@ export interface GridRowProps extends React.HTMLAttributes { */ index: number; rowHeight: number | 'auto'; - offsetTop: number | undefined; offsetLeft: number; columnsTotalWidth: number; firstColumnIndex: number; @@ -92,7 +91,6 @@ const GridRow = forwardRef(function GridRow(props, className, visibleColumns, pinnedColumns, - offsetTop, offsetLeft, columnsTotalWidth, firstColumnIndex, @@ -505,7 +503,6 @@ GridRow.propTypes = { isNotVisible: PropTypes.bool.isRequired, lastColumnIndex: PropTypes.number.isRequired, offsetLeft: PropTypes.number.isRequired, - offsetTop: PropTypes.number, onClick: PropTypes.func, onDoubleClick: PropTypes.func, onMouseEnter: PropTypes.func, diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index aad121bf44615..43036f1aed475 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -115,7 +115,6 @@ export const useGridVirtualScroller = () => { const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS); const isRtl = useRtl(); - const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const selectedRowsLookup = useGridSelector(apiRef, selectedIdsLookupSelector); const currentPage = useGridVisibleRows(apiRef); const mainRef = apiRef.current.mainElementRef; @@ -544,7 +543,6 @@ export const useGridVirtualScroller = () => { rowId={id} index={rowIndex} selected={isSelected} - offsetTop={params.rows ? undefined : rowsMeta.positions[rowIndexInPage]} offsetLeft={offsetLeft} columnsTotalWidth={dimensions.columnsTotalWidth} rowHeight={baseRowHeight} From 18e4361c3dc8b9582035d43f0f95133a6d7bfe8d Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 15:56:00 +0100 Subject: [PATCH 061/129] refactor debounce logic --- .../features/dimensions/useGridDimensions.ts | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 3148c9a10b1e4..62e3c80f8def7 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -148,18 +148,14 @@ export function useGridDimensions(apiRef: RefObject, pr rightPinnedWidth, } = getStaticDimensions(props, apiRef, densityFactor, pinnedColumns); - const [savedSize, setSavedSize] = React.useState(); - const debouncedSetSavedSize = React.useMemo( - () => throttle(setSavedSize, props.resizeThrottleMs), - [props.resizeThrottleMs], - ); - React.useEffect(() => debouncedSetSavedSize.clear, [debouncedSetSavedSize]); - const getRootDimensions = () => apiRef.current.state.dimensions; - const setDimensions = useEventCallback((dimensions: GridDimensions) => { - apiRef.current.setState((state) => ({ ...state, dimensions })); - }); + const setDimensions = React.useCallback( + (dimensions: GridDimensions) => { + apiRef.current.setState((state) => ({ ...state, dimensions })); + }, + [apiRef], + ); const getViewportPageSize = React.useCallback(() => { const dimensions = gridDimensionsSelector(apiRef.current.state); @@ -322,6 +318,19 @@ export function useGridDimensions(apiRef: RefObject, pr rightPinnedWidth, ]); + const updateDimensionCallback = useEventCallback(updateDimensions); + const debouncedUpdateDimensions = React.useMemo( + () => + props.resizeThrottleMs > 0 + ? throttle(() => { + updateDimensionCallback(); + apiRef.current.publishEvent('debouncedResize', rootDimensionsRef.current!); + }, props.resizeThrottleMs) + : undefined, + [apiRef, props.resizeThrottleMs, updateDimensionCallback], + ); + React.useEffect(() => debouncedUpdateDimensions?.clear, [debouncedUpdateDimensions]); + const apiPublic: GridDimensionsApi = { getRootDimensions, }; @@ -331,16 +340,10 @@ export function useGridDimensions(apiRef: RefObject, pr getViewportPageSize, }; + useEnhancedEffect(updateDimensions, [updateDimensions]); useGridApiMethod(apiRef, apiPublic, 'public'); useGridApiMethod(apiRef, apiPrivate, 'private'); - useEnhancedEffect(() => { - if (!isFirstSizing.current) { - updateDimensions(); - apiRef.current.publishEvent('debouncedResize', rootDimensionsRef.current!); - } - }, [apiRef, savedSize, updateDimensions]); - const root = apiRef.current.rootElementRef.current; useEnhancedEffect(() => { if (!root) { @@ -406,16 +409,16 @@ export function useGridDimensions(apiRef: RefObject, pr errorShown.current = true; } - if (isFirstSizing.current) { + if (isFirstSizing.current || !debouncedUpdateDimensions) { // We want to initialize the grid dimensions as soon as possible to avoid flickering isFirstSizing.current = false; updateDimensions(); return; } - debouncedSetSavedSize(size); + debouncedUpdateDimensions(); }, - [updateDimensions, props.autoHeight, debouncedSetSavedSize, logger], + [updateDimensions, props.autoHeight, debouncedUpdateDimensions, logger], ); useGridApiEventHandler(apiRef, 'resize', handleResize); From 4388740fdb50ee7cca6d74a5b995b6ff3a28198a Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 19:10:44 +0100 Subject: [PATCH 062/129] perf: don't filter data if there are no filters --- docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx | 2 +- .../src/hooks/features/filter/gridFilterSelector.ts | 5 ++++- .../x-data-grid/src/hooks/features/filter/useGridFilter.tsx | 6 +++++- .../src/hooks/features/rowSelection/useGridRowSelection.ts | 2 +- packages/x-data-grid/src/hooks/features/rows/useGridRows.ts | 5 ++++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx b/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx index e96ca3ac73d6a..8fa3ed82ae3a9 100644 --- a/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx +++ b/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx @@ -47,7 +47,7 @@ export default function FilteredRowCount() { (filterModel: GridFilterModel) => { const { filteredRowsLookup } = apiRef.current.getFilterState(filterModel); return Object.keys(filteredRowsLookup).filter( - (rowId) => filteredRowsLookup[rowId] === true, + (rowId) => filteredRowsLookup[rowId] !== false, ).length; }, [apiRef], diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts index 218bb839348ca..b4b4782baf865 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts @@ -5,6 +5,7 @@ import { GridStateCommunity } from '../../../models/gridStateCommunity'; import { gridSortedRowEntriesSelector } from '../sorting/gridSortingSelector'; import { gridColumnLookupSelector } from '../columns/gridColumnsSelector'; import { gridRowMaximumTreeDepthSelector, gridRowTreeSelector } from '../rows/gridRowsSelector'; +import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty'; /** * @category Filtering @@ -100,7 +101,9 @@ export const gridFilteredSortedRowEntriesSelector = createSelectorMemoized( gridFilteredRowsLookupSelector, gridSortedRowEntriesSelector, (filteredRowsLookup, sortedRows) => - sortedRows.filter((row) => filteredRowsLookup[row.id] !== false), + isObjectEmpty(filteredRowsLookup) + ? sortedRows + : sortedRows.filter((row) => filteredRowsLookup[row.id] !== false), ); /** diff --git a/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx b/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx index e0c5edc2c4a81..57204a3070675 100644 --- a/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx +++ b/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx @@ -423,7 +423,11 @@ export const useGridFilter = ( const flatFilteringMethod = React.useCallback>( (params) => { - if (props.filterMode !== 'client' || !params.isRowMatchingFilters) { + if ( + props.filterMode !== 'client' || + !params.isRowMatchingFilters || + (!params.filterModel.items.length && !params.filterModel.quickFilterValues?.length) + ) { return { filteredRowsLookup: {}, filteredChildrenCountLookup: {}, diff --git a/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts b/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts index bd3e4270c606a..3f46ce0f78080 100644 --- a/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts +++ b/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts @@ -463,7 +463,7 @@ export const useGridRowSelection = ( if (props.filterMode === 'server') { return !rowsLookup[id]; } - return filteredRowsLookup[id] !== true; + return !rowsLookup[id] || filteredRowsLookup[id] === false; }; let hasChanged = false; diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts index b7585843d04eb..d89d95cef5354 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts @@ -39,6 +39,7 @@ import { } from './gridRowsUtils'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; import { GridStrategyGroup } from '../../core/strategyProcessing'; +import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty'; export const rowsStateInitializer: GridStateInitializer< Pick @@ -329,7 +330,9 @@ export const useGridRows = ( if (applyFiltering) { const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); - children = children.filter((childId) => filteredRowsLookup[childId] !== false); + children = isObjectEmpty(filteredRowsLookup) + ? children + : children.filter((childId) => filteredRowsLookup[childId] !== false); } return children; From 4c3fda2894e4b643bdb7191ca367eee4e142d0f3 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 19:30:19 +0100 Subject: [PATCH 063/129] lint --- .../x-data-grid/src/hooks/features/filter/gridFilterSelector.ts | 2 +- packages/x-data-grid/src/hooks/features/rows/useGridRows.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts index b4b4782baf865..e28763fb63294 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts @@ -1,3 +1,4 @@ +import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty'; import { createSelector, createSelectorMemoized } from '../../../utils/createSelector'; import { GridRowId } from '../../../models/gridRows'; import { GridFilterItem } from '../../../models/gridFilterItem'; @@ -5,7 +6,6 @@ import { GridStateCommunity } from '../../../models/gridStateCommunity'; import { gridSortedRowEntriesSelector } from '../sorting/gridSortingSelector'; import { gridColumnLookupSelector } from '../columns/gridColumnsSelector'; import { gridRowMaximumTreeDepthSelector, gridRowTreeSelector } from '../rows/gridRowsSelector'; -import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty'; /** * @category Filtering diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts index d89d95cef5354..01186dd1d7231 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts @@ -1,6 +1,7 @@ import * as React from 'react'; import { RefObject } from '@mui/x-internals/types'; import useLazyRef from '@mui/utils/useLazyRef'; +import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty'; import { GridEventListener } from '../../../models/events'; import { DataGridProcessedProps } from '../../../models/props/DataGridProps'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; @@ -39,7 +40,6 @@ import { } from './gridRowsUtils'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; import { GridStrategyGroup } from '../../core/strategyProcessing'; -import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty'; export const rowsStateInitializer: GridStateInitializer< Pick From bed334e0e7132f28fd0f9a62496059288ffe7173 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 19:45:09 +0100 Subject: [PATCH 064/129] lint --- docs/data/data-grid/filtering-recipes/FilteredRowCount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/data-grid/filtering-recipes/FilteredRowCount.js b/docs/data/data-grid/filtering-recipes/FilteredRowCount.js index ce723ee414503..1a0d68c556b84 100644 --- a/docs/data/data-grid/filtering-recipes/FilteredRowCount.js +++ b/docs/data/data-grid/filtering-recipes/FilteredRowCount.js @@ -47,7 +47,7 @@ export default function FilteredRowCount() { (filterModel) => { const { filteredRowsLookup } = apiRef.current.getFilterState(filterModel); return Object.keys(filteredRowsLookup).filter( - (rowId) => filteredRowsLookup[rowId] === true, + (rowId) => filteredRowsLookup[rowId] !== false, ).length; }, [apiRef], From 281bd962e6133def202cf0c99a1e03157fdf285f Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 19:51:12 +0100 Subject: [PATCH 065/129] stable filter lookup base state --- .../src/hooks/features/filter/gridFilterState.ts | 6 ++++++ .../src/hooks/features/filter/useGridFilter.tsx | 12 +++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts index c48354461cf09..f2ae6248584f4 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts @@ -5,6 +5,12 @@ import { GridRowId, GridValidRowModel } from '../../../models/gridRows'; export type GridFilterItemResult = { [key: Required['id']]: boolean }; export type GridQuickFilterValueResult = { [key: string]: boolean }; +export const defaultGridFilterLookup = { + filteredRowsLookup: {}, + filteredChildrenCountLookup: {}, + filteredDescendantCountLookup: {}, +}; + export const getDefaultGridFilterModel: () => GridFilterModel = () => ({ items: [], logicOperator: GridLogicOperator.And, diff --git a/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx b/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx index 57204a3070675..c7e2fc2057160 100644 --- a/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx +++ b/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx @@ -15,7 +15,7 @@ import { useGridApiMethod } from '../../utils/useGridApiMethod'; import { useGridLogger } from '../../utils/useGridLogger'; import { gridColumnLookupSelector } from '../columns/gridColumnsSelector'; import { GridPreferencePanelsValue } from '../preferencesPanel/gridPreferencePanelsValue'; -import { getDefaultGridFilterModel } from './gridFilterState'; +import { defaultGridFilterLookup, getDefaultGridFilterModel } from './gridFilterState'; import { gridFilterModelSelector } from './gridFilterSelector'; import { useFirstRender } from '../../utils/useFirstRender'; import { gridRowsLookupSelector } from '../rows'; @@ -46,9 +46,7 @@ export const filterStateInitializer: GridStateInitializer< ...state, filter: { filterModel: sanitizeFilterModel(filterModel, props.disableMultipleColumnsFiltering, apiRef), - filteredRowsLookup: {}, - filteredChildrenCountLookup: {}, - filteredDescendantCountLookup: {}, + ...defaultGridFilterLookup, }, visibleRowsLookup: {}, }; @@ -428,11 +426,7 @@ export const useGridFilter = ( !params.isRowMatchingFilters || (!params.filterModel.items.length && !params.filterModel.quickFilterValues?.length) ) { - return { - filteredRowsLookup: {}, - filteredChildrenCountLookup: {}, - filteredDescendantCountLookup: {}, - }; + return defaultGridFilterLookup; } const dataRowIdToModelLookup = gridRowsLookupSelector(apiRef); From 9cfa9d958d066ab1d5bbfed27b2ff54c28081684 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 20:05:31 +0100 Subject: [PATCH 066/129] simplify --- .../src/hooks/features/filter/gridFilterSelector.ts | 7 ++----- .../src/hooks/features/filter/useGridFilter.tsx | 4 +++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts index e28763fb63294..559294471f34c 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts @@ -71,11 +71,8 @@ export const gridFilteredDescendantCountLookupSelector = createSelector( export const gridExpandedSortedRowEntriesSelector = createSelectorMemoized( gridVisibleRowsLookupSelector, gridSortedRowEntriesSelector, - gridRowMaximumTreeDepthSelector, - gridFilterModelSelector, - gridQuickFilterValuesSelector, - (visibleRowsLookup, sortedRows, maxDepth, filterModel, quickFilterValues) => { - if (maxDepth < 2 && !filterModel.items.length && !quickFilterValues?.length) { + (visibleRowsLookup, sortedRows) => { + if (isObjectEmpty(visibleRowsLookup)) { return sortedRows; } return sortedRows.filter((row) => visibleRowsLookup[row.id] !== false); diff --git a/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx b/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx index c7e2fc2057160..c07297f02d806 100644 --- a/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx +++ b/packages/x-data-grid/src/hooks/features/filter/useGridFilter.tsx @@ -454,7 +454,9 @@ export const useGridFilter = ( filterCache, ); - filteredRowsLookup[id] = isRowPassing; + if (!isRowPassing) { + filteredRowsLookup[id] = isRowPassing; + } } const footerId = 'auto-generated-group-footer-root'; From 24b5ae0079e082a049488807513086da819943d0 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 20:16:32 +0100 Subject: [PATCH 067/129] remove repeated line --- .../features/aggregation/useGridAggregationPreProcessors.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx index 9a8addd6294ec..57fc19a1ee4ba 100644 --- a/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx +++ b/packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx @@ -75,8 +75,6 @@ export const useGridAggregationPreProcessors = ( rulesOnLastColumnHydration.current = aggregationRules; apiRef.current.caches.aggregation.rulesOnLastColumnHydration = aggregationRules; - apiRef.current.caches.aggregation.rulesOnLastColumnHydration = aggregationRules; - return columnsState; }, [apiRef, props.aggregationFunctions, props.disableAggregation, props.unstable_dataSource], From a66231d6d0088abd03e7082843fa6c4534769df2 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 20:24:01 +0100 Subject: [PATCH 068/129] perf: check for autogenerated rows only if model doesn't exist --- .../src/hooks/features/sorting/gridSortingSelector.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/sorting/gridSortingSelector.ts b/packages/x-data-grid/src/hooks/features/sorting/gridSortingSelector.ts index 1022a5ee6f2c7..2751c5e2a82bd 100644 --- a/packages/x-data-grid/src/hooks/features/sorting/gridSortingSelector.ts +++ b/packages/x-data-grid/src/hooks/features/sorting/gridSortingSelector.ts @@ -33,10 +33,11 @@ export const gridSortedRowEntriesSelector = createSelectorMemoized( const model = idRowsLookup[id]; if (model) { acc.push({ id, model }); - } - const rowNode = rowTree[id]; - if (rowNode && isAutogeneratedRowNode(rowNode)) { - acc.push({ id, model: { [GRID_ID_AUTOGENERATED]: id } }); + } else { + const rowNode = rowTree[id]; + if (rowNode && isAutogeneratedRowNode(rowNode)) { + acc.push({ id, model: { [GRID_ID_AUTOGENERATED]: id } }); + } } return acc; }, [] as GridRowEntry[]), From fcd3c9c865dcc9463a624b44b79abccc9c0ea58a Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 20:26:16 +0100 Subject: [PATCH 069/129] lint `useGridDimensions` --- .../features/dimensions/useGridDimensions.ts | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 62e3c80f8def7..092e9a3fca7c2 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -76,34 +76,6 @@ const EMPTY_DIMENSIONS: GridDimensions = { bottomContainerHeight: 0, }; -const getStaticDimensions = ( - props: RootProps, - apiRef: RefObject, - density: number, - pinnedColumnns: ReturnType, -) => { - const validRowHeight = getValidRowHeight( - props.rowHeight, - DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, - rowHeightWarning, - ); - - return { - rowHeight: Math.floor(validRowHeight * density), - headerHeight: Math.floor(props.columnHeaderHeight * density), - groupHeaderHeight: Math.floor( - (props.columnGroupHeaderHeight ?? props.columnHeaderHeight) * density, - ), - headerFilterHeight: Math.floor( - (props.headerFilterHeight ?? props.columnHeaderHeight) * density, - ), - columnsTotalWidth: roundToDecimalPlaces(gridColumnsTotalWidthSelector(apiRef), 1), - headersTotalHeight: getTotalHeaderHeight(apiRef, props), - leftPinnedWidth: pinnedColumnns.left.reduce((w, col) => w + col.computedWidth, 0), - rightPinnedWidth: pinnedColumnns.right.reduce((w, col) => w + col.computedWidth, 0), - }; -}; - export const dimensionsStateInitializer: GridStateInitializer = ( state, props, @@ -425,6 +397,34 @@ export function useGridDimensions(apiRef: RefObject, pr useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); } +function getStaticDimensions( + props: RootProps, + apiRef: RefObject, + density: number, + pinnedColumnns: ReturnType, +) { + const validRowHeight = getValidRowHeight( + props.rowHeight, + DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, + rowHeightWarning, + ); + + return { + rowHeight: Math.floor(validRowHeight * density), + headerHeight: Math.floor(props.columnHeaderHeight * density), + groupHeaderHeight: Math.floor( + (props.columnGroupHeaderHeight ?? props.columnHeaderHeight) * density, + ), + headerFilterHeight: Math.floor( + (props.headerFilterHeight ?? props.columnHeaderHeight) * density, + ), + columnsTotalWidth: roundToDecimalPlaces(gridColumnsTotalWidthSelector(apiRef), 1), + headersTotalHeight: getTotalHeaderHeight(apiRef, props), + leftPinnedWidth: pinnedColumnns.left.reduce((w, col) => w + col.computedWidth, 0), + rightPinnedWidth: pinnedColumnns.right.reduce((w, col) => w + col.computedWidth, 0), + }; +} + const scrollbarSizeCache = new WeakMap(); function measureScrollbarSize(rootElement: Element | null, scrollbarSize: number | undefined) { if (scrollbarSize !== undefined) { From 10bdcd8a13149006742ce5d23618739cfed33d64 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 20:56:08 +0100 Subject: [PATCH 070/129] use empty object for `useGridSelector` deps --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 2f79673be52c1..8b8cd7aa9aed2 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -52,6 +52,8 @@ export const argsEqual = (prev: any, curr: any) => { const createRefs = () => ({ state: null, equals: null, selector: null, args: null }) as any; +const EMPTY = [] as unknown[]; + export const useGridSelector = ( apiRef: RefObject, selector: Selector, @@ -115,7 +117,8 @@ export const useGridSelector = ( setState(newState); } }); - }, [apiRef, refs]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, EMPTY); return state; }; From bf8bcf4fc9ea37fddd4a9910f3b70af92da86d64 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 21:11:11 +0100 Subject: [PATCH 071/129] fix --- packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx index 08559682d0420..d910de0a61907 100644 --- a/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/events.DataGridPro.test.tsx @@ -370,7 +370,7 @@ describe(' - Events params', () => { // Since rowheight < viewport height, onmount calls fetchRows directly expect(handleFetchRows.callCount).to.equal(1); act(() => { - apiRef.current.publishEvent('renderedRowsIntervalChange', { + apiRef.current?.publishEvent('renderedRowsIntervalChange', { firstRowIndex: 3, lastRowIndex: 10, firstColumnIndex: 0, From ac18ea55aac39e53140e173dd03da3c6caf7344a Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 23:09:42 +0100 Subject: [PATCH 072/129] fix row editing selector --- packages/x-data-grid/src/components/GridRow.tsx | 5 ++++- .../src/hooks/features/editing/gridEditingSelectors.ts | 4 +++- .../src/hooks/features/editing/useGridRowEditing.ts | 8 ++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid/src/components/GridRow.tsx b/packages/x-data-grid/src/components/GridRow.tsx index 4c3d05590585f..da359f417d686 100644 --- a/packages/x-data-grid/src/components/GridRow.tsx +++ b/packages/x-data-grid/src/components/GridRow.tsx @@ -126,7 +126,10 @@ const GridRow = forwardRef(function GridRow(props, ); const handleRef = useForkRef(ref, refProp); const rowNode = apiRef.current.getRowNode(rowId); - const editing = useGridSelector(apiRef, gridRowIsEditingSelector, rowId); + const editing = useGridSelector(apiRef, gridRowIsEditingSelector, { + rowId, + editMode: rootProps.editMode, + }); const editable = rootProps.editMode === GridEditModes.Row; const hasFocusCell = focusedColumnIndex !== undefined; const hasVirtualFocusCellLeft = diff --git a/packages/x-data-grid/src/hooks/features/editing/gridEditingSelectors.ts b/packages/x-data-grid/src/hooks/features/editing/gridEditingSelectors.ts index 988fe7f81fd92..564b5cc920d4e 100644 --- a/packages/x-data-grid/src/hooks/features/editing/gridEditingSelectors.ts +++ b/packages/x-data-grid/src/hooks/features/editing/gridEditingSelectors.ts @@ -1,6 +1,7 @@ import { createSelector } from '../../../utils/createSelector'; import { GridStateCommunity } from '../../../models/gridStateCommunity'; import { GridRowId } from '../../../models/gridRows'; +import { GridEditModes, GridEditMode } from '../../../models/gridEditRowModel'; /** * Select the row editing state. @@ -9,7 +10,8 @@ export const gridEditRowsStateSelector = (state: GridStateCommunity) => state.ed export const gridRowIsEditingSelector = createSelector( gridEditRowsStateSelector, - (editRows, rowId: GridRowId) => Boolean(editRows[rowId]), + (editRows, { rowId, editMode }: { rowId: GridRowId; editMode: GridEditMode }) => + editMode === GridEditModes.Row && Boolean(editRows[rowId]), ); export const gridEditCellStateSelector = createSelector( diff --git a/packages/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts b/packages/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts index 62f53ac3ff5a0..1302c4d1cc9f9 100644 --- a/packages/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts +++ b/packages/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts @@ -328,10 +328,10 @@ export const useGridRowEditing = ( const getRowMode = React.useCallback( (id) => { - if (props.editMode === GridEditModes.Cell) { - return GridRowModes.View; - } - const isEditing = gridRowIsEditingSelector(apiRef.current.state, id); + const isEditing = gridRowIsEditingSelector(apiRef.current.state, { + rowId: id, + editMode: props.editMode, + }); return isEditing ? GridRowModes.Edit : GridRowModes.View; }, [apiRef, props.editMode], From fc18204ab3c654ac5fa40a09be8407b68202d590 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Mon, 27 Jan 2025 23:10:25 +0100 Subject: [PATCH 073/129] lint --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 8b8cd7aa9aed2..1f072f9d14bca 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { RefObject } from '@mui/x-internals/types'; import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare'; import { warnOnce } from '@mui/x-internals/warning'; From 0cfce51e54261822c1a914d93074a87b48f7e99b Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 00:42:30 +0100 Subject: [PATCH 074/129] ci From 89328637d4895f52c5bead5ed6759d5de3497633 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 18:42:11 +0100 Subject: [PATCH 075/129] perf: improve resize performance --- .../virtualization/useGridVirtualScroller.tsx | 51 ++++++++++++++----- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index fdab38043b130..79e76baff4995 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -51,6 +51,7 @@ import { EMPTY_PINNED_COLUMN_FIELDS, GridPinnedColumns } from '../columns'; import { gridFocusedVirtualCellSelector } from './gridFocusedVirtualCellSelector'; import { roundToDecimalPlaces } from '../../../utils/roundToDecimalPlaces'; import { isJSDOM } from '../../../utils/isJSDOM'; +import { GridStateCommunity } from '../../../models/gridStateCommunity'; const MINIMUM_COLUMN_WIDTH = 50; @@ -104,8 +105,7 @@ export const useGridVirtualScroller = () => { const enabledForRows = useGridSelector(apiRef, gridVirtualizationRowEnabledSelector) && !isJSDOM; const enabledForColumns = useGridSelector(apiRef, gridVirtualizationColumnEnabledSelector) && !isJSDOM; - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); - const outerSize = dimensions.viewportOuterSize; + const pinnedRows = useGridSelector(apiRef, gridPinnedRowsSelector); const pinnedColumnDefinitions = gridVisiblePinnedColumnDefinitionsSelector(apiRef); const pinnedColumns = listView @@ -121,11 +121,16 @@ export const useGridVirtualScroller = () => { const scrollerRef = apiRef.current.virtualScrollerRef; const scrollbarVerticalRef = apiRef.current.virtualScrollbarVerticalRef; const scrollbarHorizontalRef = apiRef.current.virtualScrollbarHorizontalRef; - const contentHeight = dimensions.contentSize.height; - const columnsTotalWidth = dimensions.columnsTotalWidth; const hasColSpan = useGridSelector(apiRef, gridHasColSpanSelector); const isRenderContextReady = React.useRef(false); + const rowHeight = useGridSelector(apiRef, rowHeightSelector); + const contentHeight = useGridSelector(apiRef, contentHeightSelector); + const columnsTotalWidth = useGridSelector(apiRef, columnsTotalWidthSelector); + const needsHorizontalScrollbar = useGridSelector(apiRef, needsHorizontalScrollbarSelector); + const verticalScrollbarWidth = useGridSelector(apiRef, verticalScrollbarWidthSelector); + const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector); + const previousSize = React.useRef<{ width: number; height: number }>(null); const mainRefCallback = React.useCallback( @@ -217,7 +222,7 @@ export const useGridVirtualScroller = () => { isRtl, rootProps.rowBufferPx, rootProps.columnBufferPx, - dimensions.rowHeight * 15, + rowHeight * 15, MINIMUM_COLUMN_WIDTH * 6, ), ).current; @@ -297,8 +302,7 @@ export const useGridVirtualScroller = () => { ); // PERF: use the computed minimum column width instead of a static one - const didCrossThreshold = - rowScroll >= dimensions.rowHeight || columnScroll >= MINIMUM_COLUMN_WIDTH; + const didCrossThreshold = rowScroll >= rowHeight || columnScroll >= MINIMUM_COLUMN_WIDTH; const didChangeDirection = scrollCache.direction !== direction; const shouldUpdate = didCrossThreshold || didChangeDirection; @@ -327,7 +331,7 @@ export const useGridVirtualScroller = () => { direction, rootProps.rowBufferPx, rootProps.columnBufferPx, - dimensions.rowHeight * 15, + rowHeight * 15, MINIMUM_COLUMN_WIDTH * 6, ); @@ -537,7 +541,7 @@ export const useGridVirtualScroller = () => { index={rowIndex} selected={isSelected} offsetLeft={offsetLeft} - columnsTotalWidth={dimensions.columnsTotalWidth} + columnsTotalWidth={columnsTotalWidth} rowHeight={baseRowHeight} pinnedColumns={pinnedColumns} visibleColumns={visibleColumns} @@ -548,8 +552,8 @@ export const useGridVirtualScroller = () => { isLastVisible={isLastVisible} isNotVisible={isVirtualFocusRow} showBottomBorder={showBottomBorder} - scrollbarWidth={dimensions.hasScrollY ? dimensions.scrollbarSize : 0} - gridHasFiller={dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width} + scrollbarWidth={verticalScrollbarWidth} + gridHasFiller={gridHasFiller} {...rowProps} />, ); @@ -569,8 +573,6 @@ export const useGridVirtualScroller = () => { return rows; }; - const needsHorizontalScrollbar = outerSize.width && columnsTotalWidth > outerSize.width; - const scrollerStyle = React.useMemo( () => ({ @@ -748,6 +750,29 @@ type RenderContextInputs = { virtualizeColumnsWithAutoRowHeight: DataGridProcessedProps['virtualizeColumnsWithAutoRowHeight']; }; +// dimension selectors +function rowHeightSelector(state: GridStateCommunity) { + return state.dimensions.rowHeight; +} +function columnsTotalWidthSelector(state: GridStateCommunity) { + return state.dimensions.columnsTotalWidth; +} +function contentHeightSelector(state: GridStateCommunity) { + return state.dimensions.contentSize.height; +} +function needsHorizontalScrollbarSelector(state: GridStateCommunity) { + return ( + state.dimensions.viewportOuterSize.width > 0 && + state.dimensions.columnsTotalWidth > state.dimensions.viewportOuterSize.width + ); +} +function verticalScrollbarWidthSelector(state: GridStateCommunity) { + return state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; +} +function gridHasFillerSelector(state: GridStateCommunity) { + return state.dimensions.columnsTotalWidth < state.dimensions.viewportOuterSize.width; +} + function inputsSelector( apiRef: RefObject, rootProps: ReturnType, From c2f90cbb9ab3159e9ad2ba2ee9b448910be88b5d Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 19:56:23 +0100 Subject: [PATCH 076/129] perf: resize performance / use granular selectors for dimensions --- .../cellSelection/useGridCellSelection.ts | 8 +++-- .../columnHeaders/useGridColumnHeaders.tsx | 16 +++++---- .../useGridDataSourceLazyLoader.ts | 3 +- .../src/components/GridScrollArea.tsx | 30 +++++++++++++---- .../components/GridSkeletonLoadingOverlay.tsx | 4 +-- .../components/containers/GridRootStyles.ts | 18 ++++++---- .../virtualization/GridMainContainer.tsx | 6 ++-- .../virtualization/GridVirtualScroller.tsx | 33 +++++++++++-------- .../columnHeaders/useGridColumnHeaders.tsx | 26 ++++++++++----- .../dimensions/gridDimensionsSelectors.ts | 30 +++++++++++++++++ .../hooks/features/rows/useGridRowsMeta.ts | 12 +++---- .../virtualization/useGridVirtualScroller.tsx | 33 ++++++++----------- 12 files changed, 142 insertions(+), 77 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts b/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts index a81e42578523f..a1f121c6f31d7 100644 --- a/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts +++ b/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts @@ -70,7 +70,6 @@ export const useGridCellSelection = ( const mousePosition = React.useRef<{ x: number; y: number }>(null); const autoScrollRAF = React.useRef(null); const sortedRowIds = useGridSelector(apiRef, gridSortedRowIdsSelector); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); const totalHeaderHeight = getTotalHeaderHeight(apiRef, props); const ignoreValueFormatterProp = props.ignoreValueFormatterDuringExport; @@ -292,6 +291,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; @@ -331,7 +332,7 @@ export const useGridCellSelection = ( } autoScroll(); - }, [apiRef, dimensions, totalHeaderHeight]); + }, [apiRef, totalHeaderHeight]); const handleCellMouseOver = React.useCallback>( (params, event) => { @@ -354,6 +355,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; @@ -378,7 +380,7 @@ export const useGridCellSelection = ( stopAutoScroll(); } }, - [apiRef, startAutoScroll, stopAutoScroll, totalHeaderHeight, dimensions], + [apiRef, startAutoScroll, stopAutoScroll, totalHeaderHeight], ); const handleCellClick = useEventCallback< diff --git a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 66b8d90ac05f5..d7a6311e7c1a3 100644 --- a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -6,7 +6,10 @@ import { gridTabIndexColumnHeaderFilterSelector, getDataGridUtilityClass, GridFilterItem, - gridDimensionsSelector, + gridDimensionsColumnsTotalWidthSelector, + gridHasFillerSelector, + gridHeaderFilterHeightSelector, + gridVerticalScrollbarWidthSelector, } from '@mui/x-data-grid'; import { useGridColumnHeaders as useGridColumnHeadersCommunity, @@ -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, gridDimensionsColumnsTotalWidthSelector); + const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector); + const headerFilterHeight = useGridSelector(apiRef, gridHeaderFilterHeightSelector); + const scrollbarWidth = useGridSelector(apiRef, gridVerticalScrollbarWidthSelector); const columnHeaderFilterFocus = useGridSelector(apiRef, gridFocusColumnHeaderFilterSelector); @@ -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, ); @@ -146,7 +150,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { (null); @@ -322,6 +321,7 @@ export const useGridDataSourceLazyLoader = ( return; } + const dimensions = gridDimensionsSelector(privateApiRef.current.state); const position = newScrollPosition.top + dimensions.viewportInnerSize.height; const target = dimensions.contentSize.height - props.scrollEndThreshold; @@ -347,7 +347,6 @@ export const useGridDataSourceLazyLoader = ( props.scrollEndThreshold, sortModel, filterModel, - dimensions, paginationModel.pageSize, adjustRowParams, ], diff --git a/packages/x-data-grid/src/components/GridScrollArea.tsx b/packages/x-data-grid/src/components/GridScrollArea.tsx index 268a29a0572d1..90f0be98cc465 100644 --- a/packages/x-data-grid/src/components/GridScrollArea.tsx +++ b/packages/x-data-grid/src/components/GridScrollArea.tsx @@ -13,13 +13,16 @@ import { getDataGridUtilityClass, gridClasses } from '../constants'; import { useGridApiContext } from '../hooks/utils/useGridApiContext'; import { useGridApiEventHandler } from '../hooks/utils/useGridApiEventHandler'; import { useGridSelector } from '../hooks/utils/useGridSelector'; -import { gridDimensionsSelector } from '../hooks/features/dimensions/gridDimensionsSelectors'; +import { + gridDimensionsColumnsTotalWidthSelector, + gridDimensionsSelector, +} from '../hooks/features/dimensions/gridDimensionsSelectors'; import { gridDensityFactorSelector } from '../hooks/features/density/densitySelector'; -import { gridColumnsTotalWidthSelector } from '../hooks/features/columns/gridColumnsSelector'; import { GridScrollParams } from '../models/params/gridScrollParams'; import { GridEventListener } from '../models/events'; import { useTimeout } from '../hooks/utils/useTimeout'; import { getTotalHeaderHeight } from '../hooks/features/columns/gridColumnsUtils'; +import { createSelector } from '../utils/createSelector'; const CLIFF = 1; const SLOP = 1.5; @@ -62,14 +65,27 @@ const GridScrollAreaRawRoot = styled('div', { }, })); +const offsetSelector = createSelector( + gridDimensionsSelector, + (dimensions, direction: ScrollAreaProps['scrollDirection']) => { + if (direction === 'left') { + return dimensions.leftPinnedWidth; + } + if (direction === 'right') { + return dimensions.rightPinnedWidth + (dimensions.hasScrollX ? dimensions.scrollbarSize : 0); + } + return 0; + }, +); + function GridScrollAreaRaw(props: ScrollAreaProps) { const { scrollDirection } = props; const rootRef = React.useRef(null); const apiRef = useGridApiContext(); const timeout = useTimeout(); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); - const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); + const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); + const sideOffset = useGridSelector(apiRef, offsetSelector, scrollDirection); const scrollPosition = React.useRef({ left: 0, @@ -77,6 +93,7 @@ function GridScrollAreaRaw(props: ScrollAreaProps) { }); const getCanScrollMore = () => { + const dimensions = gridDimensionsSelector(apiRef.current.state); if (scrollDirection === 'left') { // Only render if the user has not reached yet the start of the list return scrollPosition.current.left > 0; @@ -106,10 +123,9 @@ function GridScrollAreaRaw(props: ScrollAreaProps) { }; if (scrollDirection === 'left') { - style.left = dimensions.leftPinnedWidth; + style.left = sideOffset; } else if (scrollDirection === 'right') { - style.right = - dimensions.rightPinnedWidth + (dimensions.hasScrollX ? dimensions.scrollbarSize : 0); + style.right = sideOffset; } const handleScrolling: GridEventListener<'scrollPositionChange'> = (newScrollPosition) => { diff --git a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx index b17a03a468401..9eb3aff5df7db 100644 --- a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx +++ b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx @@ -9,7 +9,7 @@ import { useGridApiContext } from '../hooks/utils/useGridApiContext'; import { useGridRootProps } from '../hooks/utils/useGridRootProps'; import { gridColumnPositionsSelector, - gridColumnsTotalWidthSelector, + gridDimensionsColumnsTotalWidthSelector, gridDimensionsSelector, gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, @@ -64,7 +64,7 @@ const GridSkeletonLoadingOverlay = forwardRef positions.filter((value) => value <= totalWidth).length, diff --git a/packages/x-data-grid/src/components/containers/GridRootStyles.ts b/packages/x-data-grid/src/components/containers/GridRootStyles.ts index 04fa2f9316cab..ba86cf0214649 100644 --- a/packages/x-data-grid/src/components/containers/GridRootStyles.ts +++ b/packages/x-data-grid/src/components/containers/GridRootStyles.ts @@ -13,7 +13,7 @@ import { gridClasses as c } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; import { useGridSelector } from '../../hooks/utils/useGridSelector'; import { useGridPrivateApiContext } from '../../hooks/utils/useGridPrivateApiContext'; -import { gridDimensionsSelector } from '../../hooks/features/dimensions/gridDimensionsSelectors'; +import { GridStateCommunity } from '../../models/gridStateCommunity'; export type OwnerState = DataGridProcessedProps; @@ -54,6 +54,10 @@ const separatorIconDragStyles = { const ignoreSsrWarning = '/* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */'; +const shouldShowBorderTopRightRadiusSelector = (state: GridStateCommunity) => + state.dimensions.hasScrollX && + (!state.dimensions.hasScrollY || state.dimensions.scrollbarSize === 0); + export const GridRootStyles = styled('div', { name: 'MuiDataGrid', slot: 'Root', @@ -179,7 +183,10 @@ export const GridRootStyles = styled('div', { ], })<{ ownerState: OwnerState }>(({ theme: t }) => { const apiRef = useGridPrivateApiContext(); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); + const shouldShowBorderTopRightRadius = useGridSelector( + apiRef, + shouldShowBorderTopRightRadiusSelector, + ); const borderColor = getBorderColor(t); const radius = t.shape.borderRadius; @@ -371,10 +378,9 @@ export const GridRootStyles = styled('div', { borderTopLeftRadius: 'calc(var(--unstable_DataGrid-radius) - 1px)', }, [`&.${c['root--noToolbar']} [aria-rowindex="1"] .${c['columnHeader--last']}`]: { - borderTopRightRadius: - dimensions.hasScrollX && (!dimensions.hasScrollY || dimensions.scrollbarSize === 0) - ? 'calc(var(--unstable_DataGrid-radius) - 1px)' - : undefined, + borderTopRightRadius: shouldShowBorderTopRightRadius + ? 'calc(var(--unstable_DataGrid-radius) - 1px)' + : undefined, }, [`& .${c.columnHeaderCheckbox}, & .${c.cellCheckbox}`]: { padding: 0, diff --git a/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx b/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx index be3e3aadabbb8..e09227daa4e17 100644 --- a/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx @@ -4,7 +4,6 @@ import { forwardRef } from '@mui/x-internals/forwardRef'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { useGridConfiguration } from '../../hooks/utils/useGridConfiguration'; -import { GridDimensions } from '../../hooks/features/dimensions'; import { GridLoadingOverlayVariant } from '../GridLoadingOverlay'; const GridPanelAnchor = styled('div')({ @@ -15,7 +14,8 @@ const GridPanelAnchor = styled('div')({ }); type OwnerState = Pick & { - dimensions: GridDimensions; + hasScrollX: boolean; + hasPinnedRight: boolean; loadingOverlayVariant: GridLoadingOverlayVariant | null; }; @@ -26,7 +26,7 @@ const Element = styled('div', { const { ownerState } = props; return [ styles.main, - ownerState.dimensions.rightPinnedWidth > 0 && styles['main--hasPinnedRight'], + ownerState.hasPinnedRight && styles['main--hasPinnedRight'], ownerState.loadingOverlayVariant === 'skeleton' && styles['main--hasSkeletonLoadingOverlay'], ]; }, diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index 4063e6bc47ae2..2e0554789ba01 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -7,7 +7,6 @@ import { useGridApiContext } from '../../hooks/utils/useGridApiContext'; import { useGridSelector } from '../../hooks/utils/useGridSelector'; import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; -import { GridDimensions, gridDimensionsSelector } from '../../hooks/features/dimensions'; import { useGridVirtualScroller } from '../../hooks/features/virtualization/useGridVirtualScroller'; import { useGridOverlays } from '../../hooks/features/overlays/useGridOverlays'; import { GridHeaders } from '../GridHeaders'; @@ -19,21 +18,27 @@ import { GridVirtualScrollerFiller as SpaceFiller } from './GridVirtualScrollerF import { GridVirtualScrollerRenderZone as RenderZone } from './GridVirtualScrollerRenderZone'; import { GridVirtualScrollbar as Scrollbar } from './GridVirtualScrollbar'; import { GridLoadingOverlayVariant } from '../GridLoadingOverlay'; +import { + gridHasScrollXSelector, + gridHasScrollYSelector, +} from '../../hooks/features/dimensions/gridDimensionsSelectors'; +import { GridStateCommunity } from '../../models/gridStateCommunity'; type OwnerState = Pick & { - dimensions: GridDimensions; + hasScrollX: boolean; + hasPinnedRight: boolean; loadingOverlayVariant: GridLoadingOverlayVariant | null; }; const useUtilityClasses = (ownerState: OwnerState) => { - const { classes, dimensions, loadingOverlayVariant } = ownerState; + const { classes, hasScrollX, hasPinnedRight, loadingOverlayVariant } = ownerState; const slots = { root: [ 'main', - dimensions.rightPinnedWidth > 0 && 'main--hasPinnedRight', + hasPinnedRight && 'main--hasPinnedRight', loadingOverlayVariant === 'skeleton' && 'main--hasSkeletonLoadingOverlay', ], - scroller: ['virtualScroller', dimensions.hasScrollX && 'virtualScroller--hasScrollX'], + scroller: ['virtualScroller', hasScrollX && 'virtualScroller--hasScrollX'], }; return composeClasses(slots, getDataGridUtilityClass, classes); @@ -44,10 +49,7 @@ const Scroller = styled('div', { slot: 'VirtualScroller', overridesResolver: (props, styles) => { const { ownerState } = props; - return [ - styles.virtualScroller, - ownerState.dimensions.hasScrollX && styles['virtualScroller--hasScrollX'], - ]; + return [styles.virtualScroller, ownerState.hasScrollX && styles['virtualScroller--hasScrollX']]; }, })<{ ownerState: OwnerState }>({ position: 'relative', @@ -69,6 +71,8 @@ const Scroller = styled('div', { zIndex: 0, }); +const hasPinnedRightSelector = (state: GridStateCommunity) => state.dimensions.rightPinnedWidth > 0; + export interface GridVirtualScrollerProps { children?: React.ReactNode; } @@ -76,11 +80,14 @@ export interface GridVirtualScrollerProps { function GridVirtualScroller(props: GridVirtualScrollerProps) { const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); + const hasScrollY = useGridSelector(apiRef, gridHasScrollYSelector); + const hasScrollX = useGridSelector(apiRef, gridHasScrollXSelector); + const hasPinnedRight = useGridSelector(apiRef, hasPinnedRightSelector); const { getOverlay, overlaysProps } = useGridOverlays(); const ownerState = { classes: rootProps.classes, - dimensions, + hasScrollX, + hasPinnedRight, loadingOverlayVariant: overlaysProps.loadingOverlayVariant, }; const classes = useUtilityClasses(ownerState); @@ -123,10 +130,10 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { - {dimensions.hasScrollX && !rootProps.unstable_listView && ( + {hasScrollX && !rootProps.unstable_listView && ( )} - {dimensions.hasScrollY && } + {hasScrollY && } {props.children} ); diff --git a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 821dd9a80638a..4ececf4f41e12 100644 --- a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -9,7 +9,13 @@ import type { GridColumnsRenderContext } from '../../../models/params/gridScroll import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler'; import { GridEventListener } from '../../../models/events'; import { GridColumnHeaderItem } from '../../../components/columnHeaders/GridColumnHeaderItem'; -import { gridDimensionsSelector } from '../dimensions'; +import { + gridDimensionsColumnsTotalWidthSelector, + gridGroupHeaderHeightSelector, + gridHasFillerSelector, + gridHeaderHeightSelector, + gridVerticalScrollbarWidthSelector, +} from '../dimensions'; import { gridRenderContextColumnsSelector } from '../virtualization'; import { computeOffsetLeft } from '../virtualization/useGridVirtualScroller'; import { GridColumnGroupHeader } from '../../../components/columnHeaders/GridColumnGroupHeader'; @@ -99,14 +105,17 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { const apiRef = useGridPrivateApiContext(); const rootProps = useGridRootProps(); - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); const columnGroupsModel = useGridSelector(apiRef, gridColumnGroupsUnwrappedModelSelector); const columnPositions = useGridSelector(apiRef, gridColumnPositionsSelector); const renderContext = useGridSelector(apiRef, gridRenderContextColumnsSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const columnsLookup = useGridSelector(apiRef, gridColumnLookupSelector); const offsetLeft = computeOffsetLeft(columnPositions, renderContext, pinnedColumns.left.length); - const gridHasFiller = dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width; + const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); + const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector); + const headerHeight = useGridSelector(apiRef, gridHeaderHeightSelector); + const groupHeaderHeight = useGridSelector(apiRef, gridGroupHeaderHeightSelector); + const scrollbarWidth = useGridSelector(apiRef, gridVerticalScrollbarWidthSelector); const handleColumnResizeStart = React.useCallback>( (params) => setResizeCol(params.field), @@ -221,13 +230,13 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { const hasFocus = columnHeaderFocus !== null && columnHeaderFocus.field === colDef.field; const open = columnMenuState.open && columnMenuState.field === colDef.field; const pinnedPosition = params?.position; - const scrollbarWidth = dimensions.hasScrollY ? dimensions.scrollbarSize : 0; + const pinnedOffset = getPinnedCellOffset( pinnedPosition, colDef.computedWidth, columnIndex, columnPositions, - dimensions.columnsTotalWidth, + columnsTotalWidth, scrollbarWidth, ); @@ -262,7 +271,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { filterItemsCounter={ filterColumnLookup[colDef.field] && filterColumnLookup[colDef.field].length } - headerHeight={dimensions.headerHeight} + headerHeight={headerHeight} isDragging={colDef.field === dragCol} colDef={colDef} colIndex={columnIndex} @@ -396,13 +405,12 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { }; const pinnedPosition = params.position; - const scrollbarWidth = dimensions.hasScrollY ? dimensions.scrollbarSize : 0; const pinnedOffset = getPinnedCellOffset( pinnedPosition, headerInfo.width, columnIndex, columnPositions, - dimensions.columnsTotalWidth, + columnsTotalWidth, scrollbarWidth, ); @@ -424,7 +432,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { depth={depth} isLastColumn={index === visibleColumnGroupHeader.length - 1} maxDepth={headerGroupingMaxDepth} - height={dimensions.groupHeaderHeight} + height={groupHeaderHeight} hasFocus={hasFocus} tabIndex={tabIndex} pinnedPosition={pinnedPosition} diff --git a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts index 2365ce546492f..36d8a67474aff 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts @@ -1,3 +1,33 @@ import { GridStateCommunity } from '../../../models/gridStateCommunity'; export const gridDimensionsSelector = (state: GridStateCommunity) => state.dimensions; + +/** + * @ignore internal use + */ +export const gridRowHeightSelector = (state: GridStateCommunity) => state.dimensions.rowHeight; + +export const gridDimensionsColumnsTotalWidthSelector = (state: GridStateCommunity) => + state.dimensions.columnsTotalWidth; + +export const gridContentHeightSelector = (state: GridStateCommunity) => + state.dimensions.contentSize.height; + +export const gridHasScrollXSelector = (state: GridStateCommunity) => state.dimensions.hasScrollX; + +export const gridHasScrollYSelector = (state: GridStateCommunity) => state.dimensions.hasScrollY; + +export const gridHasFillerSelector = (state: GridStateCommunity) => + state.dimensions.columnsTotalWidth < state.dimensions.viewportOuterSize.width; + +export const gridHeaderHeightSelector = (state: GridStateCommunity) => + state.dimensions.headerHeight; + +export const gridGroupHeaderHeightSelector = (state: GridStateCommunity) => + state.dimensions.groupHeaderHeight; + +export const gridHeaderFilterHeightSelector = (state: GridStateCommunity) => + state.dimensions.headerFilterHeight; + +export const gridVerticalScrollbarWidthSelector = (state: GridStateCommunity) => + state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 14ef77612145a..839d406e353d4 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -18,7 +18,10 @@ import { gridSortModelSelector } from '../sorting/gridSortingSelector'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; import { gridPinnedRowsSelector, gridRowCountSelector } from './gridRowsSelector'; -import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; +import { + gridDimensionsSelector, + gridRowHeightSelector, +} from '../dimensions/gridDimensionsSelectors'; import { getValidRowHeight, getRowHeightWarning } from './gridRowsUtils'; import type { HeightEntry } from './gridRowsMetaInterfaces'; @@ -29,7 +32,7 @@ export const rowsMetaStateInitializer: GridStateInitializer = (state, props, api heights: new Map(), }; - const baseRowHeight = gridDimensionsSelector(apiRef.current.state).rowHeight; + const baseRowHeight = gridRowHeightSelector(apiRef.current.state); const dataRowCount = gridRowCountSelector(apiRef.current.state); const pagination = gridPaginationSelector(apiRef.current.state); const rowCount = Math.min( @@ -77,10 +80,7 @@ export const useGridRowsMeta = ( const sortModel = useGridSelector(apiRef, gridSortModelSelector); const currentPage = useGridVisibleRows(apiRef, props); const pinnedRows = useGridSelector(apiRef, gridPinnedRowsSelector); - const rowHeight = useGridSelector( - apiRef, - () => gridDimensionsSelector(apiRef.current.state).rowHeight, - ); + const rowHeight = useGridSelector(apiRef, gridRowHeightSelector); const getRowHeightEntry: GridRowsMetaPrivateApi['getRowHeightEntry'] = (rowId) => { let entry = heightCache.get(rowId); diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 79e76baff4995..c1aa94694e33f 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -20,7 +20,14 @@ import { gridColumnPositionsSelector, gridHasColSpanSelector, } from '../columns/gridColumnsSelector'; -import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; +import { + gridDimensionsColumnsTotalWidthSelector, + gridContentHeightSelector, + gridDimensionsSelector, + gridHasFillerSelector, + gridRowHeightSelector, + gridVerticalScrollbarWidthSelector, +} from '../dimensions/gridDimensionsSelectors'; import { gridPinnedRowsSelector } from '../rows/gridRowsSelector'; import { GridPinnedRowsPosition } from '../rows/gridRowsInterfaces'; import { useGridVisibleRows, getVisibleRows } from '../../utils/useGridVisibleRows'; @@ -124,11 +131,11 @@ export const useGridVirtualScroller = () => { const hasColSpan = useGridSelector(apiRef, gridHasColSpanSelector); const isRenderContextReady = React.useRef(false); - const rowHeight = useGridSelector(apiRef, rowHeightSelector); - const contentHeight = useGridSelector(apiRef, contentHeightSelector); - const columnsTotalWidth = useGridSelector(apiRef, columnsTotalWidthSelector); + const rowHeight = useGridSelector(apiRef, gridRowHeightSelector); + const contentHeight = useGridSelector(apiRef, gridContentHeightSelector); + const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); const needsHorizontalScrollbar = useGridSelector(apiRef, needsHorizontalScrollbarSelector); - const verticalScrollbarWidth = useGridSelector(apiRef, verticalScrollbarWidthSelector); + const verticalScrollbarWidth = useGridSelector(apiRef, gridVerticalScrollbarWidthSelector); const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector); const previousSize = React.useRef<{ width: number; height: number }>(null); @@ -269,6 +276,7 @@ export const useGridVirtualScroller = () => { return undefined; } + const dimensions = gridDimensionsSelector(apiRef.current.state); const maxScrollTop = Math.ceil( dimensions.minimumSize.height - dimensions.viewportOuterSize.height, ); @@ -751,27 +759,12 @@ type RenderContextInputs = { }; // dimension selectors -function rowHeightSelector(state: GridStateCommunity) { - return state.dimensions.rowHeight; -} -function columnsTotalWidthSelector(state: GridStateCommunity) { - return state.dimensions.columnsTotalWidth; -} -function contentHeightSelector(state: GridStateCommunity) { - return state.dimensions.contentSize.height; -} function needsHorizontalScrollbarSelector(state: GridStateCommunity) { return ( state.dimensions.viewportOuterSize.width > 0 && state.dimensions.columnsTotalWidth > state.dimensions.viewportOuterSize.width ); } -function verticalScrollbarWidthSelector(state: GridStateCommunity) { - return state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; -} -function gridHasFillerSelector(state: GridStateCommunity) { - return state.dimensions.columnsTotalWidth < state.dimensions.viewportOuterSize.width; -} function inputsSelector( apiRef: RefObject, From b600821a799d81681371a4063e80cc8fb109a4d1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 20:06:06 +0100 Subject: [PATCH 077/129] ci From c78076c874f6ae11928ab79be4bb0e14abc61c89 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 21:34:52 +0100 Subject: [PATCH 078/129] reorg --- .../columnHeaders/useGridColumnHeaders.tsx | 8 ++--- .../src/components/GridScrollArea.tsx | 6 ++-- .../virtualization/GridVirtualScroller.tsx | 8 ++--- .../dimensions/gridDimensionsSelectors.ts | 30 ------------------- .../hooks/features/rows/useGridRowsMeta.ts | 6 ++-- .../virtualization/useGridVirtualScroller.tsx | 16 +++++----- packages/x-data-grid/src/internals/index.ts | 2 ++ .../internals/selectors/dimensionSelectors.ts | 28 +++++++++++++++++ 8 files changed, 50 insertions(+), 54 deletions(-) create mode 100644 packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts diff --git a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index d7a6311e7c1a3..a3273e480edba 100644 --- a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -6,12 +6,13 @@ import { gridTabIndexColumnHeaderFilterSelector, getDataGridUtilityClass, GridFilterItem, +} from '@mui/x-data-grid'; +import { gridDimensionsColumnsTotalWidthSelector, gridHasFillerSelector, gridHeaderFilterHeightSelector, gridVerticalScrollbarWidthSelector, -} from '@mui/x-data-grid'; -import { + useGridColumnHeaders as useGridColumnHeadersCommunity, UseGridColumnHeadersProps, GetHeadersParams, @@ -21,8 +22,7 @@ import { GridColumnHeaderRow, shouldCellShowLeftBorder, shouldCellShowRightBorder, - PinnedColumnPosition, -} from '@mui/x-data-grid/internals'; + PinnedColumnPosition} from '@mui/x-data-grid/internals'; import composeClasses from '@mui/utils/composeClasses'; import { useGridRootProps } from '../../utils/useGridRootProps'; import { DataGridProProcessedProps } from '../../../models/dataGridProProps'; diff --git a/packages/x-data-grid/src/components/GridScrollArea.tsx b/packages/x-data-grid/src/components/GridScrollArea.tsx index 90f0be98cc465..47efdb7d773d8 100644 --- a/packages/x-data-grid/src/components/GridScrollArea.tsx +++ b/packages/x-data-grid/src/components/GridScrollArea.tsx @@ -13,10 +13,8 @@ import { getDataGridUtilityClass, gridClasses } from '../constants'; import { useGridApiContext } from '../hooks/utils/useGridApiContext'; import { useGridApiEventHandler } from '../hooks/utils/useGridApiEventHandler'; import { useGridSelector } from '../hooks/utils/useGridSelector'; -import { - gridDimensionsColumnsTotalWidthSelector, - gridDimensionsSelector, -} from '../hooks/features/dimensions/gridDimensionsSelectors'; +import { gridDimensionsSelector } from '../hooks/features/dimensions/gridDimensionsSelectors'; +import { gridDimensionsColumnsTotalWidthSelector } from '../internals/selectors/dimensionSelectors'; import { gridDensityFactorSelector } from '../hooks/features/density/densitySelector'; import { GridScrollParams } from '../models/params/gridScrollParams'; import { GridEventListener } from '../models/events'; diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index 2e0554789ba01..05d7164d8137d 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -1,6 +1,10 @@ import * as React from 'react'; import { styled } from '@mui/system'; import composeClasses from '@mui/utils/composeClasses'; +import { + gridHasScrollXSelector, + gridHasScrollYSelector, +} from '../../internals/selectors/dimensionSelectors'; import { GridScrollArea } from '../GridScrollArea'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { useGridApiContext } from '../../hooks/utils/useGridApiContext'; @@ -18,10 +22,6 @@ import { GridVirtualScrollerFiller as SpaceFiller } from './GridVirtualScrollerF import { GridVirtualScrollerRenderZone as RenderZone } from './GridVirtualScrollerRenderZone'; import { GridVirtualScrollbar as Scrollbar } from './GridVirtualScrollbar'; import { GridLoadingOverlayVariant } from '../GridLoadingOverlay'; -import { - gridHasScrollXSelector, - gridHasScrollYSelector, -} from '../../hooks/features/dimensions/gridDimensionsSelectors'; import { GridStateCommunity } from '../../models/gridStateCommunity'; type OwnerState = Pick & { diff --git a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts index 36d8a67474aff..2365ce546492f 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts @@ -1,33 +1,3 @@ import { GridStateCommunity } from '../../../models/gridStateCommunity'; export const gridDimensionsSelector = (state: GridStateCommunity) => state.dimensions; - -/** - * @ignore internal use - */ -export const gridRowHeightSelector = (state: GridStateCommunity) => state.dimensions.rowHeight; - -export const gridDimensionsColumnsTotalWidthSelector = (state: GridStateCommunity) => - state.dimensions.columnsTotalWidth; - -export const gridContentHeightSelector = (state: GridStateCommunity) => - state.dimensions.contentSize.height; - -export const gridHasScrollXSelector = (state: GridStateCommunity) => state.dimensions.hasScrollX; - -export const gridHasScrollYSelector = (state: GridStateCommunity) => state.dimensions.hasScrollY; - -export const gridHasFillerSelector = (state: GridStateCommunity) => - state.dimensions.columnsTotalWidth < state.dimensions.viewportOuterSize.width; - -export const gridHeaderHeightSelector = (state: GridStateCommunity) => - state.dimensions.headerHeight; - -export const gridGroupHeaderHeightSelector = (state: GridStateCommunity) => - state.dimensions.groupHeaderHeight; - -export const gridHeaderFilterHeightSelector = (state: GridStateCommunity) => - state.dimensions.headerFilterHeight; - -export const gridVerticalScrollbarWidthSelector = (state: GridStateCommunity) => - state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 839d406e353d4..d936dff14f48d 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -2,6 +2,7 @@ import * as React from 'react'; import { RefObject } from '@mui/x-internals/types'; import useLazyRef from '@mui/utils/useLazyRef'; import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils'; +import { gridRowHeightSelector } from '../../../internals/selectors/dimensionSelectors'; import { ResizeObserver } from '../../../utils/ResizeObserver'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { GridRowsMetaApi, GridRowsMetaPrivateApi } from '../../../models/api/gridRowsMetaApi'; @@ -18,10 +19,7 @@ import { gridSortModelSelector } from '../sorting/gridSortingSelector'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; import { gridPinnedRowsSelector, gridRowCountSelector } from './gridRowsSelector'; -import { - gridDimensionsSelector, - gridRowHeightSelector, -} from '../dimensions/gridDimensionsSelectors'; +import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; import { getValidRowHeight, getRowHeightWarning } from './gridRowsUtils'; import type { HeightEntry } from './gridRowsMetaInterfaces'; diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index c1aa94694e33f..bf77fe7dd319d 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -9,6 +9,13 @@ import useLazyRef from '@mui/utils/useLazyRef'; import useTimeout from '@mui/utils/useTimeout'; import { useRtl } from '@mui/system/RtlProvider'; import reactMajor from '@mui/x-internals/reactMajor'; +import { + gridDimensionsColumnsTotalWidthSelector, + gridContentHeightSelector, + gridHasFillerSelector, + gridRowHeightSelector, + gridVerticalScrollbarWidthSelector, +} from '../../../internals/selectors/dimensionSelectors'; import type { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext'; import { useGridRootProps } from '../../utils/useGridRootProps'; @@ -20,14 +27,7 @@ import { gridColumnPositionsSelector, gridHasColSpanSelector, } from '../columns/gridColumnsSelector'; -import { - gridDimensionsColumnsTotalWidthSelector, - gridContentHeightSelector, - gridDimensionsSelector, - gridHasFillerSelector, - gridRowHeightSelector, - gridVerticalScrollbarWidthSelector, -} from '../dimensions/gridDimensionsSelectors'; +import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; import { gridPinnedRowsSelector } from '../rows/gridRowsSelector'; import { GridPinnedRowsPosition } from '../rows/gridRowsInterfaces'; import { useGridVisibleRows, getVisibleRows } from '../../utils/useGridVisibleRows'; diff --git a/packages/x-data-grid/src/internals/index.ts b/packages/x-data-grid/src/internals/index.ts index bb1c26c53c34b..bdf8e32ed5ccf 100644 --- a/packages/x-data-grid/src/internals/index.ts +++ b/packages/x-data-grid/src/internals/index.ts @@ -179,3 +179,5 @@ export { serializeCellValue } from '../hooks/features/export/serializers/csvSeri export * from './utils'; export * from './constants'; export type { Localization } from '../utils/getGridLocalization'; + +export * from './selectors/dimensionSelectors'; diff --git a/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts b/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts new file mode 100644 index 0000000000000..f31247fcc8f8f --- /dev/null +++ b/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts @@ -0,0 +1,28 @@ +import { GridStateCommunity } from '../../models/gridStateCommunity'; + +export const gridRowHeightSelector = (state: GridStateCommunity) => state.dimensions.rowHeight; + +export const gridDimensionsColumnsTotalWidthSelector = (state: GridStateCommunity) => + state.dimensions.columnsTotalWidth; + +export const gridContentHeightSelector = (state: GridStateCommunity) => + state.dimensions.contentSize.height; + +export const gridHasScrollXSelector = (state: GridStateCommunity) => state.dimensions.hasScrollX; + +export const gridHasScrollYSelector = (state: GridStateCommunity) => state.dimensions.hasScrollY; + +export const gridHasFillerSelector = (state: GridStateCommunity) => + state.dimensions.columnsTotalWidth < state.dimensions.viewportOuterSize.width; + +export const gridHeaderHeightSelector = (state: GridStateCommunity) => + state.dimensions.headerHeight; + +export const gridGroupHeaderHeightSelector = (state: GridStateCommunity) => + state.dimensions.groupHeaderHeight; + +export const gridHeaderFilterHeightSelector = (state: GridStateCommunity) => + state.dimensions.headerFilterHeight; + +export const gridVerticalScrollbarWidthSelector = (state: GridStateCommunity) => + state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; From bc44121a2f055670c51ea5980367fcbf0d99d2d6 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 21:42:53 +0100 Subject: [PATCH 079/129] fix --- .../src/hooks/features/columnHeaders/useGridColumnHeaders.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 4ececf4f41e12..b9e77645abc39 100644 --- a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -15,7 +15,7 @@ import { gridHasFillerSelector, gridHeaderHeightSelector, gridVerticalScrollbarWidthSelector, -} from '../dimensions'; +} from '../../../internals/selectors/dimensionSelectors'; import { gridRenderContextColumnsSelector } from '../virtualization'; import { computeOffsetLeft } from '../virtualization/useGridVirtualScroller'; import { GridColumnGroupHeader } from '../../../components/columnHeaders/GridColumnGroupHeader'; From e8b451ccfc4e6a125c57f19ead21ea46005804c1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 21:45:04 +0100 Subject: [PATCH 080/129] fix --- .../src/hooks/features/columnHeaders/useGridColumnHeaders.tsx | 4 ++-- .../x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index a3273e480edba..8e35f73432c89 100644 --- a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -12,7 +12,6 @@ import { gridHasFillerSelector, gridHeaderFilterHeightSelector, gridVerticalScrollbarWidthSelector, - useGridColumnHeaders as useGridColumnHeadersCommunity, UseGridColumnHeadersProps, GetHeadersParams, @@ -22,7 +21,8 @@ import { GridColumnHeaderRow, shouldCellShowLeftBorder, shouldCellShowRightBorder, - PinnedColumnPosition} from '@mui/x-data-grid/internals'; + PinnedColumnPosition, +} from '@mui/x-data-grid/internals'; import composeClasses from '@mui/utils/composeClasses'; import { useGridRootProps } from '../../utils/useGridRootProps'; import { DataGridProProcessedProps } from '../../../models/dataGridProProps'; diff --git a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx index 9eb3aff5df7db..2c91ddbe23c3e 100644 --- a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx +++ b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx @@ -9,7 +9,6 @@ import { useGridApiContext } from '../hooks/utils/useGridApiContext'; import { useGridRootProps } from '../hooks/utils/useGridRootProps'; import { gridColumnPositionsSelector, - gridDimensionsColumnsTotalWidthSelector, gridDimensionsSelector, gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, @@ -17,6 +16,7 @@ import { useGridSelector, } from '../hooks'; import { PinnedColumnPosition } from '../internals/constants'; +import { gridDimensionsColumnsTotalWidthSelector } from '../internals/selectors/dimensionSelectors'; import { GridEventListener } from '../models'; import { DataGridProcessedProps } from '../models/props/DataGridProps'; import { getDataGridUtilityClass, gridClasses } from '../constants/gridClasses'; From 5b0df331dfeed6e75494967d2394ac8f03d89683 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 22:50:37 +0100 Subject: [PATCH 081/129] fix styles re-evaluating on each render --- .../src/DataGridPremium/DataGridPremium.tsx | 8 +++++++- packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx b/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx index 5fa2f15565440..0e9e6f808eebf 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx +++ b/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx @@ -47,6 +47,12 @@ const DataGridPremiumRaw = forwardRef(function DataGridPremium , + [], + ); + return ( - + {watermark} ); diff --git a/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx b/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx index 37d8c05460ed9..da900b0e56d55 100644 --- a/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx +++ b/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx @@ -34,6 +34,11 @@ const DataGridProRaw = forwardRef(function DataGridPro , + [], + ); + return ( - + {watermark} ); From 5e4eb36365f7bb760d940bfd09feb8494010fe01 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Tue, 28 Jan 2025 22:58:17 +0100 Subject: [PATCH 082/129] watermark as const --- .../src/DataGridPremium/DataGridPremium.tsx | 6 +----- packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx | 5 +---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx b/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx index 0e9e6f808eebf..c470e57eebff7 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx +++ b/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx @@ -29,6 +29,7 @@ const configuration = { }, }; const releaseInfo = getReleaseInfo(); +const watermark = ; let dataGridPremiumPropValidators: PropValidator[]; @@ -48,11 +49,6 @@ const DataGridPremiumRaw = forwardRef(function DataGridPremium , - [], - ); - return ( ; const DataGridProRaw = forwardRef(function DataGridPro( inProps: DataGridProProps, @@ -34,10 +35,6 @@ const DataGridProRaw = forwardRef(function DataGridPro , - [], - ); return ( From f2b57b0ddc29a457dedb92fc7c1388a872cb54ba Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 00:52:28 +0100 Subject: [PATCH 083/129] perf: +10-15 fps --- .../infiniteLoader/useGridInfiniteLoader.tsx | 11 ++-- .../virtualization/GridVirtualScroller.tsx | 22 +++++-- .../features/dimensions/useGridDimensions.ts | 63 +++++++++---------- .../hooks/features/rows/gridRowsSelector.ts | 16 +++++ .../internals/selectors/dimensionSelectors.ts | 20 ++++++ 5 files changed, 88 insertions(+), 44 deletions(-) diff --git a/packages/x-data-grid-pro/src/hooks/features/infiniteLoader/useGridInfiniteLoader.tsx b/packages/x-data-grid-pro/src/hooks/features/infiniteLoader/useGridInfiniteLoader.tsx index 61a5fabda0729..ae1b6f11d06ea 100644 --- a/packages/x-data-grid-pro/src/hooks/features/infiniteLoader/useGridInfiniteLoader.tsx +++ b/packages/x-data-grid-pro/src/hooks/features/infiniteLoader/useGridInfiniteLoader.tsx @@ -5,12 +5,12 @@ import { useGridApiOptionHandler, gridVisibleColumnDefinitionsSelector, useGridApiMethod, - gridDimensionsSelector, } from '@mui/x-data-grid'; import { useGridVisibleRows, GridInfiniteLoaderPrivateApi, useTimeout, + gridHorizontalScrollbarHeightSelector, } from '@mui/x-data-grid/internals'; import useEventCallback from '@mui/utils/useEventCallback'; import { styled } from '@mui/system'; @@ -64,10 +64,6 @@ export const useGridInfiniteLoader = ( }); const virtualScroller = apiRef.current.virtualScrollerRef.current; - const dimensions = useGridSelector(apiRef, gridDimensionsSelector); - - const marginBottom = - props.scrollEndThreshold - (dimensions.hasScrollX ? dimensions.scrollbarSize : 0); React.useEffect(() => { if (!isEnabled) { @@ -78,6 +74,9 @@ export const useGridInfiniteLoader = ( } observer.current?.disconnect(); + const horizontalScrollbarHeight = gridHorizontalScrollbarHeightSelector(apiRef.current.state); + const marginBottom = props.scrollEndThreshold - horizontalScrollbarHeight; + observer.current = new IntersectionObserver(handleLoadMoreRows, { threshold: 1, root: virtualScroller, @@ -86,7 +85,7 @@ export const useGridInfiniteLoader = ( if (triggerElement.current) { observer.current.observe(triggerElement.current); } - }, [virtualScroller, handleLoadMoreRows, isEnabled, marginBottom]); + }, [apiRef, virtualScroller, handleLoadMoreRows, isEnabled, props.scrollEndThreshold]); const updateTarget = (node: HTMLElement | null) => { if (triggerElement.current !== node) { diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index 05d7164d8137d..cbf8fd392b0df 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { styled } from '@mui/system'; import composeClasses from '@mui/utils/composeClasses'; import { + gridHasPinnedFillerSelector, gridHasScrollXSelector, gridHasScrollYSelector, } from '../../internals/selectors/dimensionSelectors'; @@ -23,6 +24,10 @@ import { GridVirtualScrollerRenderZone as RenderZone } from './GridVirtualScroll import { GridVirtualScrollbar as Scrollbar } from './GridVirtualScrollbar'; import { GridLoadingOverlayVariant } from '../GridLoadingOverlay'; import { GridStateCommunity } from '../../models/gridStateCommunity'; +import { + gridHasBottomPinnedRowsSelector, + gridHasTopPinnedRowsSelector, +} from '../../hooks/features/rows/gridRowsSelector'; type OwnerState = Pick & { hasScrollX: boolean; @@ -82,7 +87,10 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { const rootProps = useGridRootProps(); const hasScrollY = useGridSelector(apiRef, gridHasScrollYSelector); const hasScrollX = useGridSelector(apiRef, gridHasScrollXSelector); + const hasTopPinnedRows = useGridSelector(apiRef, gridHasTopPinnedRowsSelector); + const hasBottomPinnedRows = useGridSelector(apiRef, gridHasBottomPinnedRowsSelector); const hasPinnedRight = useGridSelector(apiRef, hasPinnedRightSelector); + const hasPinnedFiller = useGridSelector(apiRef, gridHasPinnedFillerSelector); const { getOverlay, overlaysProps } = useGridOverlays(); const ownerState = { classes: rootProps.classes, @@ -112,7 +120,9 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { {!rootProps.unstable_listView && } - + {hasTopPinnedRows && ( + + )} {getOverlay()} @@ -124,11 +134,13 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { - + {hasPinnedFiller && } - - - + {hasBottomPinnedRows && ( + + + + )} {hasScrollX && !rootProps.unstable_listView && ( diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 092e9a3fca7c2..b87bea7782520 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -103,7 +103,6 @@ export function useGridDimensions(apiRef: RefObject, pr const logger = useGridLogger(apiRef, 'useResizeContainer'); const errorShown = React.useRef(false); const rootDimensionsRef = React.useRef(EMPTY_SIZE); - const dimensionsState = useGridSelector(apiRef, gridDimensionsSelector); const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); @@ -120,11 +119,20 @@ export function useGridDimensions(apiRef: RefObject, pr rightPinnedWidth, } = getStaticDimensions(props, apiRef, densityFactor, pinnedColumns); - const getRootDimensions = () => apiRef.current.state.dimensions; + const getRootDimensions = React.useCallback( + () => gridDimensionsSelector(apiRef.current.state), + [apiRef], + ); const setDimensions = React.useCallback( (dimensions: GridDimensions) => { apiRef.current.setState((state) => ({ ...state, dimensions })); + if (apiRef.current.rootElementRef.current) { + setCSSVariables( + apiRef.current.rootElementRef.current, + gridDimensionsSelector(apiRef.current.state), + ); + } }, [apiRef], ); @@ -321,37 +329,8 @@ export function useGridDimensions(apiRef: RefObject, pr if (!root) { return; } - - const set = (k: string, v: string) => root.style.setProperty(k, v); - set('--DataGrid-width', `${dimensionsState.viewportOuterSize.width}px`); - set('--DataGrid-hasScrollX', `${Number(dimensionsState.hasScrollX)}`); - set('--DataGrid-hasScrollY', `${Number(dimensionsState.hasScrollY)}`); - set('--DataGrid-scrollbarSize', `${dimensionsState.scrollbarSize}px`); - set('--DataGrid-rowWidth', `${dimensionsState.rowWidth}px`); - set('--DataGrid-columnsTotalWidth', `${dimensionsState.columnsTotalWidth}px`); - set('--DataGrid-leftPinnedWidth', `${dimensionsState.leftPinnedWidth}px`); - set('--DataGrid-rightPinnedWidth', `${dimensionsState.rightPinnedWidth}px`); - set('--DataGrid-headerHeight', `${dimensionsState.headerHeight}px`); - set('--DataGrid-headersTotalHeight', `${dimensionsState.headersTotalHeight}px`); - set('--DataGrid-topContainerHeight', `${dimensionsState.topContainerHeight}px`); - set('--DataGrid-bottomContainerHeight', `${dimensionsState.bottomContainerHeight}px`); - set('--height', `${dimensionsState.rowHeight}px`); - }, [ - root, - dimensionsState.viewportOuterSize.width, - dimensionsState.hasScrollX, - dimensionsState.hasScrollY, - dimensionsState.scrollbarSize, - dimensionsState.rowWidth, - dimensionsState.columnsTotalWidth, - dimensionsState.leftPinnedWidth, - dimensionsState.rightPinnedWidth, - dimensionsState.headerHeight, - dimensionsState.headersTotalHeight, - dimensionsState.topContainerHeight, - dimensionsState.bottomContainerHeight, - dimensionsState.rowHeight, - ]); + setCSSVariables(root, gridDimensionsSelector(apiRef.current.state)); + }, [apiRef, root]); const handleResize = React.useCallback>( (size) => { @@ -397,6 +376,24 @@ export function useGridDimensions(apiRef: RefObject, pr useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); } +function setCSSVariables(root: HTMLElement, dimensions: GridDimensions) { + const set = (k: string, v: string) => root.style.setProperty(k, v); + // @deprecated due to extensive dom updates + // set('--DataGrid-width', `${dimensions.viewportOuterSize.width}px`); + set('--DataGrid-hasScrollX', `${Number(dimensions.hasScrollX)}`); + set('--DataGrid-hasScrollY', `${Number(dimensions.hasScrollY)}`); + set('--DataGrid-scrollbarSize', `${dimensions.scrollbarSize}px`); + set('--DataGrid-rowWidth', `${dimensions.rowWidth}px`); + set('--DataGrid-columnsTotalWidth', `${dimensions.columnsTotalWidth}px`); + set('--DataGrid-leftPinnedWidth', `${dimensions.leftPinnedWidth}px`); + set('--DataGrid-rightPinnedWidth', `${dimensions.rightPinnedWidth}px`); + set('--DataGrid-headerHeight', `${dimensions.headerHeight}px`); + set('--DataGrid-headersTotalHeight', `${dimensions.headersTotalHeight}px`); + set('--DataGrid-topContainerHeight', `${dimensions.topContainerHeight}px`); + set('--DataGrid-bottomContainerHeight', `${dimensions.bottomContainerHeight}px`); + set('--height', `${dimensions.rowHeight}px`); +} + function getStaticDimensions( props: RootProps, apiRef: RefObject, diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts index 2cfb32ed68156..1c703eac2ef78 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts @@ -95,6 +95,22 @@ export const gridPinnedRowsSelector = createSelectorMemoized( }, ); +/** + * @ignore - do not document. + */ +export const gridHasTopPinnedRowsSelector = createSelectorMemoized( + gridAdditionalRowGroupsSelector, + (additionalRowGroups) => Boolean(additionalRowGroups?.pinnedRows?.top?.length), +); + +/** + * @ignore - do not document. + */ +export const gridHasBottomPinnedRowsSelector = createSelectorMemoized( + gridAdditionalRowGroupsSelector, + (additionalRowGroups) => Boolean(additionalRowGroups?.pinnedRows?.bottom?.length), +); + /** * @ignore - do not document. */ diff --git a/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts b/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts index f31247fcc8f8f..6a5bf73c349d3 100644 --- a/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts +++ b/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts @@ -26,3 +26,23 @@ export const gridHeaderFilterHeightSelector = (state: GridStateCommunity) => export const gridVerticalScrollbarWidthSelector = (state: GridStateCommunity) => state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; + +export const gridHorizontalScrollbarHeightSelector = (state: GridStateCommunity) => + state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; + +export const gridHasPinnedFillerSelector = (state: GridStateCommunity) => { + const hasPinnedColumns = + state.dimensions.leftPinnedWidth > 0 || state.dimensions.rightPinnedWidth > 0; + if (!hasPinnedColumns) { + return false; + } + const height = state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; + const needsLastRowBorder = + state.dimensions.viewportOuterSize.height - state.dimensions.minimumSize.height > 0; + + if (height === 0 && !needsLastRowBorder) { + return false; + } + + return true; +}; From cf2cd6676568fabf90f597c4a70444277e589696 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 01:06:50 +0100 Subject: [PATCH 084/129] ci From d8e7f0c3a8ee0df9629947a2732b529a11457594 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 01:46:54 +0100 Subject: [PATCH 085/129] fix tests --- .../src/components/virtualization/GridVirtualScroller.tsx | 6 +++--- .../src/internals/selectors/dimensionSelectors.ts | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index cbf8fd392b0df..82e96d19e0446 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { styled } from '@mui/system'; import composeClasses from '@mui/utils/composeClasses'; import { - gridHasPinnedFillerSelector, + gridHasBottomFillerSelector, gridHasScrollXSelector, gridHasScrollYSelector, } from '../../internals/selectors/dimensionSelectors'; @@ -90,7 +90,7 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { const hasTopPinnedRows = useGridSelector(apiRef, gridHasTopPinnedRowsSelector); const hasBottomPinnedRows = useGridSelector(apiRef, gridHasBottomPinnedRowsSelector); const hasPinnedRight = useGridSelector(apiRef, hasPinnedRightSelector); - const hasPinnedFiller = useGridSelector(apiRef, gridHasPinnedFillerSelector); + const hasBottomFiller = useGridSelector(apiRef, gridHasBottomFillerSelector); const { getOverlay, overlaysProps } = useGridOverlays(); const ownerState = { classes: rootProps.classes, @@ -134,7 +134,7 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { - {hasPinnedFiller && } + {hasBottomFiller && } {hasBottomPinnedRows && ( diff --git a/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts b/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts index 6a5bf73c349d3..9e836ee313534 100644 --- a/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts +++ b/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts @@ -30,12 +30,7 @@ export const gridVerticalScrollbarWidthSelector = (state: GridStateCommunity) => export const gridHorizontalScrollbarHeightSelector = (state: GridStateCommunity) => state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; -export const gridHasPinnedFillerSelector = (state: GridStateCommunity) => { - const hasPinnedColumns = - state.dimensions.leftPinnedWidth > 0 || state.dimensions.rightPinnedWidth > 0; - if (!hasPinnedColumns) { - return false; - } +export const gridHasBottomFillerSelector = (state: GridStateCommunity) => { const height = state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; const needsLastRowBorder = state.dimensions.viewportOuterSize.height - state.dimensions.minimumSize.height > 0; From 51eea10a84f20031f636d52aaae60cb684f218b1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 09:02:14 +0100 Subject: [PATCH 086/129] fix --- .../src/hooks/features/columns/gridColumnsSelector.ts | 6 +++++- .../src/hooks/features/dimensions/useGridDimensions.ts | 6 ++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts b/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts index f252388bc18f0..f660021ad3908 100644 --- a/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts +++ b/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts @@ -6,6 +6,7 @@ import { EMPTY_PINNED_COLUMN_FIELDS, } from './gridColumnsInterfaces'; import { gridIsRtlSelector } from '../../core/gridCoreSelector'; +import { roundToDecimalPlaces } from '../../../utils/roundToDecimalPlaces'; /** * Get the columns state @@ -161,7 +162,10 @@ export const gridColumnsTotalWidthSelector = createSelector( if (colCount === 0) { return 0; } - return positions[colCount - 1] + visibleColumns[colCount - 1].computedWidth; + return roundToDecimalPlaces( + positions[colCount - 1] + visibleColumns[colCount - 1].computedWidth, + 1, + ); }, ); diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index b87bea7782520..88a110f208458 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -106,6 +106,7 @@ export function useGridDimensions(apiRef: RefObject, pr const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); + const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); const isFirstSizing = React.useRef(true); const { @@ -113,7 +114,6 @@ export function useGridDimensions(apiRef: RefObject, pr headerHeight, groupHeaderHeight, headerFilterHeight, - columnsTotalWidth, headersTotalHeight, leftPinnedWidth, rightPinnedWidth, @@ -378,8 +378,6 @@ export function useGridDimensions(apiRef: RefObject, pr function setCSSVariables(root: HTMLElement, dimensions: GridDimensions) { const set = (k: string, v: string) => root.style.setProperty(k, v); - // @deprecated due to extensive dom updates - // set('--DataGrid-width', `${dimensions.viewportOuterSize.width}px`); set('--DataGrid-hasScrollX', `${Number(dimensions.hasScrollX)}`); set('--DataGrid-hasScrollY', `${Number(dimensions.hasScrollY)}`); set('--DataGrid-scrollbarSize', `${dimensions.scrollbarSize}px`); @@ -415,7 +413,7 @@ function getStaticDimensions( headerFilterHeight: Math.floor( (props.headerFilterHeight ?? props.columnHeaderHeight) * density, ), - columnsTotalWidth: roundToDecimalPlaces(gridColumnsTotalWidthSelector(apiRef), 1), + columnsTotalWidth: gridColumnsTotalWidthSelector(apiRef), headersTotalHeight: getTotalHeaderHeight(apiRef, props), leftPinnedWidth: pinnedColumnns.left.reduce((w, col) => w + col.computedWidth, 0), rightPinnedWidth: pinnedColumnns.right.reduce((w, col) => w + col.computedWidth, 0), From 560a43632fa07a60f92739f67e17ba9a25f4b3bc Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 13:26:42 +0100 Subject: [PATCH 087/129] ci From c3f54b3d744f34f0ee3d7486dbc4f18de884058b Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 15:45:02 +0100 Subject: [PATCH 088/129] fix test --- .../src/hooks/features/serverSideTreeData/utils.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts index 677f7210c9274..5991b82cd2476 100644 --- a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts +++ b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts @@ -1,20 +1,19 @@ import { GridRowId, GridRowTreeConfig, GRID_ROOT_GROUP_ID } from '@mui/x-data-grid'; +import { defaultGridFilterLookup } from '@mui/x-data-grid/hooks/features/filter/gridFilterState'; import { getTreeNodeDescendants } from '@mui/x-data-grid/internals'; export function skipFiltering(rowTree: GridRowTreeConfig) { - const filteredRowsLookup: Record = {}; const filteredChildrenCountLookup: Record = {}; const filteredDescendantCountLookup: Record = {}; const nodes = Object.values(rowTree); for (let i = 0; i < nodes.length; i += 1) { const node: any = nodes[i]; - filteredRowsLookup[node.id] = true; filteredChildrenCountLookup[node.id] = node.serverChildrenCount ?? 0; } return { - filteredRowsLookup, + filteredRowsLookup: defaultGridFilterLookup.filteredRowsLookup, filteredChildrenCountLookup, filteredDescendantCountLookup, }; From 1c5fc8c781b34549a58b8545f0be4ecf0346bdd3 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 15:54:17 +0100 Subject: [PATCH 089/129] lint --- .../src/hooks/features/serverSideTreeData/utils.ts | 3 +-- packages/x-data-grid/src/internals/index.ts | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts index 5991b82cd2476..d146069703239 100644 --- a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts +++ b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts @@ -1,6 +1,5 @@ import { GridRowId, GridRowTreeConfig, GRID_ROOT_GROUP_ID } from '@mui/x-data-grid'; -import { defaultGridFilterLookup } from '@mui/x-data-grid/hooks/features/filter/gridFilterState'; -import { getTreeNodeDescendants } from '@mui/x-data-grid/internals'; +import { defaultGridFilterLookup, getTreeNodeDescendants } from '@mui/x-data-grid/internals'; export function skipFiltering(rowTree: GridRowTreeConfig) { const filteredChildrenCountLookup: Record = {}; diff --git a/packages/x-data-grid/src/internals/index.ts b/packages/x-data-grid/src/internals/index.ts index 6fc97e604a206..14a491cc80231 100644 --- a/packages/x-data-grid/src/internals/index.ts +++ b/packages/x-data-grid/src/internals/index.ts @@ -61,6 +61,7 @@ export { useGridDensity, densityStateInitializer } from '../hooks/features/densi export { useGridCsvExport } from '../hooks/features/export/useGridCsvExport'; export { useGridPrintExport } from '../hooks/features/export/useGridPrintExport'; export { useGridFilter, filterStateInitializer } from '../hooks/features/filter/useGridFilter'; +export { defaultGridFilterLookup } from '../hooks/features/filter/gridFilterState'; export { passFilterLogic } from '../hooks/features/filter/gridFilterUtils'; export { gridFilteredChildrenCountLookupSelector, From 3a574067390028d9d9cfecbfb9fa977955a89c82 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Wed, 29 Jan 2025 16:30:42 +0100 Subject: [PATCH 090/129] stable obj --- .../src/hooks/features/serverSideTreeData/utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts index d146069703239..f319a36f07ef6 100644 --- a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts +++ b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts @@ -3,7 +3,6 @@ import { defaultGridFilterLookup, getTreeNodeDescendants } from '@mui/x-data-gri export function skipFiltering(rowTree: GridRowTreeConfig) { const filteredChildrenCountLookup: Record = {}; - const filteredDescendantCountLookup: Record = {}; const nodes = Object.values(rowTree); for (let i = 0; i < nodes.length; i += 1) { @@ -14,7 +13,7 @@ export function skipFiltering(rowTree: GridRowTreeConfig) { return { filteredRowsLookup: defaultGridFilterLookup.filteredRowsLookup, filteredChildrenCountLookup, - filteredDescendantCountLookup, + filteredDescendantCountLookup: defaultGridFilterLookup.filteredDescendantCountLookup, }; } From ffa1efcc96d8993c319d62094274c7aa16d785f2 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 30 Jan 2025 14:05:28 +0100 Subject: [PATCH 091/129] reduce unnecessary calls to `hydrateRowsMeta` --- .../x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index d936dff14f48d..61f681ad4cf08 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -73,9 +73,6 @@ export const useGridRowsMeta = ( const isHeightMetaValid = React.useRef(false); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); - const filterModel = useGridSelector(apiRef, gridFilterModelSelector); - const paginationState = useGridSelector(apiRef, gridPaginationSelector); - const sortModel = useGridSelector(apiRef, gridSortModelSelector); const currentPage = useGridVisibleRows(apiRef, props); const pinnedRows = useGridSelector(apiRef, gridPinnedRowsSelector); const rowHeight = useGridSelector(apiRef, gridRowHeightSelector); @@ -275,7 +272,7 @@ export const useGridRowsMeta = ( // Because of variable row height this is needed for the virtualization useEnhancedEffect(() => { hydrateRowsMeta(); - }, [filterModel, paginationState, sortModel, hydrateRowsMeta]); + }, [hydrateRowsMeta]); const rowsMetaApi: GridRowsMetaApi = { unstable_getRowHeight: getRowHeight, From ae6cc13790a0e16f758eef425139a0fabd530317 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 30 Jan 2025 14:21:45 +0100 Subject: [PATCH 092/129] lint --- packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 61f681ad4cf08..c462779d16826 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -13,9 +13,7 @@ import { useGridApiMethod } from '../../utils/useGridApiMethod'; import { GridRowEntry } from '../../../models/gridRows'; import { useGridSelector } from '../../utils/useGridSelector'; import { gridDensityFactorSelector } from '../density/densitySelector'; -import { gridFilterModelSelector } from '../filter/gridFilterSelector'; import { gridPaginationSelector } from '../pagination/gridPaginationSelector'; -import { gridSortModelSelector } from '../sorting/gridSortingSelector'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; import { gridPinnedRowsSelector, gridRowCountSelector } from './gridRowsSelector'; From 34f24b38ce21972c522bb4a6ef34a599e03d4c4f Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 30 Jan 2025 23:52:23 +0100 Subject: [PATCH 093/129] fix recipe --- docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx b/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx index 92ffbc44e5d10..9e80a5c1af8c6 100644 --- a/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx +++ b/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx @@ -45,15 +45,14 @@ export default function FilteredRowCount() { const getFilteredRowsCount = React.useCallback( (filterModel: GridFilterModel) => { + const rowIds = apiRef.current?.getAllRowIds(); const filterState = apiRef.current?.getFilterState(filterModel); - if (!filterState) { + if (!rowIds || !filterState) { return 0; } const { filteredRowsLookup } = filterState; - return Object.keys(filteredRowsLookup).filter( - (rowId) => filteredRowsLookup[rowId] !== false, - ).length; + return rowIds.filter((rowId) => filteredRowsLookup[rowId] !== false).length; }, [apiRef], ); From 56f75fa5e5d2ec8692dc44835f78d8157182b3cb Mon Sep 17 00:00:00 2001 From: lauri865 Date: Thu, 30 Jan 2025 23:58:43 +0100 Subject: [PATCH 094/129] lint --- docs/data/data-grid/filtering-recipes/FilteredRowCount.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/data/data-grid/filtering-recipes/FilteredRowCount.js b/docs/data/data-grid/filtering-recipes/FilteredRowCount.js index 71a4580345f27..7d633e0838567 100644 --- a/docs/data/data-grid/filtering-recipes/FilteredRowCount.js +++ b/docs/data/data-grid/filtering-recipes/FilteredRowCount.js @@ -45,15 +45,14 @@ export default function FilteredRowCount() { const getFilteredRowsCount = React.useCallback( (filterModel) => { + const rowIds = apiRef.current?.getAllRowIds(); const filterState = apiRef.current?.getFilterState(filterModel); - if (!filterState) { + if (!rowIds || !filterState) { return 0; } const { filteredRowsLookup } = filterState; - return Object.keys(filteredRowsLookup).filter( - (rowId) => filteredRowsLookup[rowId] !== false, - ).length; + return rowIds.filter((rowId) => filteredRowsLookup[rowId] !== false).length; }, [apiRef], ); From 2415b59b1a870c230a6d10c71c5b202fbf772dd1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 01:04:17 +0100 Subject: [PATCH 095/129] fix grid selector timing issue --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 1f072f9d14bca..2648cba64cfa4 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -104,7 +104,7 @@ export const useGridSelector = ( } } - useEnhancedEffect(() => { + React.useInsertionEffect(() => { return apiRef.current.store.subscribe(() => { const newState = applySelector( apiRef, From b63c07a3883dae1a451fe08dc9f00f5f23d00c80 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 01:07:30 +0100 Subject: [PATCH 096/129] lint --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 2648cba64cfa4..246c46052db14 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -1,5 +1,4 @@ import * as React from 'react'; -import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { RefObject } from '@mui/x-internals/types'; import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare'; import { warnOnce } from '@mui/x-internals/warning'; From 37cf7696ef21512e87959f0e5f49a185f8632c45 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 01:14:31 +0100 Subject: [PATCH 097/129] lint --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 246c46052db14..5ac6de0123bf9 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -116,7 +116,6 @@ export const useGridSelector = ( setState(newState); } }); - // eslint-disable-next-line react-hooks/exhaustive-deps }, EMPTY); return state; From b10a81fd2ab8aebbebb03b81aa112ace50979a37 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 09:37:34 +0100 Subject: [PATCH 098/129] readability --- packages/x-data-grid/src/hooks/utils/useIsSSR.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/x-data-grid/src/hooks/utils/useIsSSR.ts b/packages/x-data-grid/src/hooks/utils/useIsSSR.ts index ecc9e929993ea..f40364e068971 100644 --- a/packages/x-data-grid/src/hooks/utils/useIsSSR.ts +++ b/packages/x-data-grid/src/hooks/utils/useIsSSR.ts @@ -1,10 +1,7 @@ import { useSyncExternalStore } from 'use-sync-external-store/shim'; const emptySubscribe = () => () => {}; +const clientSnapshot = () => false; +const serverSnapshot = () => true; -export const useIsSSR = () => - useSyncExternalStore( - emptySubscribe, - () => false, - () => true, - ); +export const useIsSSR = () => useSyncExternalStore(emptySubscribe, clientSnapshot, serverSnapshot); From 45f70a14873aed856c792bc0edfe2d46d889d597 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 10:18:08 +0100 Subject: [PATCH 099/129] add `rootMount` event --- .../src/components/containers/GridRoot.tsx | 13 ++++++++++- .../features/dimensions/useGridDimensions.ts | 22 +++++++++---------- .../src/models/events/gridEventLookup.ts | 4 ++++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/x-data-grid/src/components/containers/GridRoot.tsx b/packages/x-data-grid/src/components/containers/GridRoot.tsx index 34fe5e434b46f..42cfbd9d949db 100644 --- a/packages/x-data-grid/src/components/containers/GridRoot.tsx +++ b/packages/x-data-grid/src/components/containers/GridRoot.tsx @@ -54,7 +54,18 @@ const GridRoot = forwardRef(function GridRoot(pro const apiRef = useGridPrivateApiContext(); const density = useGridSelector(apiRef, gridDensitySelector); const rootElementRef = apiRef.current.rootElementRef; - const handleRef = useForkRef(rootElementRef, ref); + + const rootMountCallback = React.useCallback( + (node: HTMLElement | null) => { + if (node === null) { + return; + } + apiRef.current.publishEvent('rootMount', node); + }, + [apiRef], + ); + + const handleRef = useForkRef(rootElementRef, ref, rootMountCallback); const ownerState = rootProps; diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 88a110f208458..ef6a55b5bc802 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -9,10 +9,7 @@ import { throttle } from '@mui/x-internals/throttle'; import { GridEventListener } from '../../../models/events'; import { ElementSize } from '../../../models'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; -import { - useGridApiEventHandler, - useGridApiOptionHandler, -} from '../../utils/useGridApiEventHandler'; +import { useGridApiOptionHandler } from '../../utils/useGridApiEventHandler'; import { useGridApiMethod } from '../../utils/useGridApiMethod'; import { useGridLogger } from '../../utils/useGridLogger'; import { DataGridProcessedProps } from '../../../models/props/DataGridProps'; @@ -324,13 +321,12 @@ export function useGridDimensions(apiRef: RefObject, pr useGridApiMethod(apiRef, apiPublic, 'public'); useGridApiMethod(apiRef, apiPrivate, 'private'); - const root = apiRef.current.rootElementRef.current; - useEnhancedEffect(() => { - if (!root) { - return; - } - setCSSVariables(root, gridDimensionsSelector(apiRef.current.state)); - }, [apiRef, root]); + const handleRootMount = React.useCallback>( + (root) => { + setCSSVariables(root, gridDimensionsSelector(apiRef.current.state)); + }, + [apiRef], + ); const handleResize = React.useCallback>( (size) => { @@ -372,12 +368,14 @@ export function useGridDimensions(apiRef: RefObject, pr [updateDimensions, props.autoHeight, debouncedUpdateDimensions, logger], ); - useGridApiEventHandler(apiRef, 'resize', handleResize); + useGridApiOptionHandler(apiRef, 'rootMount', handleRootMount); + useGridApiOptionHandler(apiRef, 'resize', handleResize); useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); } function setCSSVariables(root: HTMLElement, dimensions: GridDimensions) { const set = (k: string, v: string) => root.style.setProperty(k, v); + set('--DataGrid-width', `${dimensions.viewportOuterSize.width}px`); set('--DataGrid-hasScrollX', `${Number(dimensions.hasScrollX)}`); set('--DataGrid-hasScrollY', `${Number(dimensions.hasScrollY)}`); set('--DataGrid-scrollbarSize', `${dimensions.scrollbarSize}px`); diff --git a/packages/x-data-grid/src/models/events/gridEventLookup.ts b/packages/x-data-grid/src/models/events/gridEventLookup.ts index 80198a32f8481..9f37ed2ede1d4 100644 --- a/packages/x-data-grid/src/models/events/gridEventLookup.ts +++ b/packages/x-data-grid/src/models/events/gridEventLookup.ts @@ -399,6 +399,10 @@ export interface GridEventLookup GridColumnGroupHeaderEventLookup, GridCellEventLookup, GridControlledStateEventLookup { + /** + * Fired when rootElementRef.current becomes available. + */ + rootMount: { params: HTMLElement }; /** * Fired when the grid is unmounted. */ From d92c4d886606890d835a57ca573d3ed8da8870c1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 10:57:01 +0100 Subject: [PATCH 100/129] use `useSyncExternalStore` for `useGridSelector` --- docs/data/data-grid/events/events.json | 7 ++ .../src/hooks/utils/useGridSelector.ts | 86 ++++++++++--------- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/docs/data/data-grid/events/events.json b/docs/data/data-grid/events/events.json index fedd745dd5c45..26bc1b73ed3e6 100644 --- a/docs/data/data-grid/events/events.json +++ b/docs/data/data-grid/events/events.json @@ -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", diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 5ac6de0123bf9..74c2921b75d40 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -2,6 +2,7 @@ import * as React from 'react'; import { RefObject } from '@mui/x-internals/types'; import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare'; import { warnOnce } from '@mui/x-internals/warning'; +import { useSyncExternalStore } from 'use-sync-external-store/shim'; import type { GridApiCommon } from '../../models/api/gridApiCommon'; import type { OutputSelector } from '../../utils/createSelector'; import { useLazyRef } from './useLazyRef'; @@ -49,10 +50,39 @@ export const argsEqual = (prev: any, curr: any) => { return fn(prev, curr); }; -const createRefs = () => ({ state: null, equals: null, selector: null, args: null }) as any; +const createRefs = () => + ({ state: null, equals: null, selector: null, args: null, argsId: 0 }) as any; const EMPTY = [] as unknown[]; +type Refs = { + state: T; + equals: (a: U, b: U) => boolean; + selector: Selector; + args: any; + argsId: number; +}; + +const getState = ( + apiRef: RefObject, + refs: RefObject>, + listener?: (state: T) => void, +) => { + const newState = applySelector( + apiRef, + refs.current.selector, + refs.current.args, + apiRef.current.instanceId, + ) as T; + if (!refs.current.equals(refs.current.state, newState)) { + refs.current.state = newState; + if (listener) { + return listener(newState); + } + } + return refs.current.state; +}; + export const useGridSelector = ( apiRef: RefObject, selector: Selector, @@ -68,55 +98,31 @@ export const useGridSelector = ( } } - const refs = useLazyRef< - { - state: T; - equals: typeof equals; - selector: typeof selector; - args: typeof args; - }, - never - >(createRefs); + const refs = useLazyRef, never>(createRefs); const didInit = refs.current.selector !== null; - const [state, setState] = React.useState( - // We don't use an initialization function to avoid allocations - (didInit ? null : applySelector(apiRef, selector, args, apiRef.current.instanceId)) as T, - ); - - refs.current.state = state; refs.current.equals = equals; refs.current.selector = selector; const prevArgs = refs.current.args; refs.current.args = args; if (didInit && !argsEqual(prevArgs, args)) { - const newState = applySelector( - apiRef, - refs.current.selector, - refs.current.args, - apiRef.current.instanceId, - ) as T; - if (!refs.current.equals(refs.current.state, newState)) { - refs.current.state = newState; - setState(newState); - } + refs.current.argsId += 1; } - React.useInsertionEffect(() => { - return apiRef.current.store.subscribe(() => { - const newState = applySelector( - apiRef, - refs.current.selector, - refs.current.args, - apiRef.current.instanceId, - ) as T; - if (!refs.current.equals(refs.current.state, newState)) { - refs.current.state = newState; - setState(newState); - } - }); - }, EMPTY); + const getSnapShot = React.useCallback( + () => getState(apiRef, refs), + // eslint-disable-next-line react-hooks/exhaustive-deps + [apiRef, refs.current.argsId], + ); + + const subscribe = React.useCallback( + (listener: (state: T) => void) => + apiRef.current.store.subscribe(() => getState(apiRef, refs, listener)), + // eslint-disable-next-line react-hooks/exhaustive-deps + EMPTY, + ); + const state = useSyncExternalStore(subscribe, getSnapShot, getSnapShot); return state; }; From 25998ecf04cd8cf3fa053f04f9bebff48e054147 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 11:17:22 +0100 Subject: [PATCH 101/129] fix --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 74c2921b75d40..046ee6afa5ab8 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -67,7 +67,7 @@ const getState = ( apiRef: RefObject, refs: RefObject>, listener?: (state: T) => void, -) => { +): T => { const newState = applySelector( apiRef, refs.current.selector, @@ -77,7 +77,7 @@ const getState = ( if (!refs.current.equals(refs.current.state, newState)) { refs.current.state = newState; if (listener) { - return listener(newState); + listener(newState); } } return refs.current.state; @@ -123,6 +123,6 @@ export const useGridSelector = ( EMPTY, ); - const state = useSyncExternalStore(subscribe, getSnapShot, getSnapShot); + const state = useSyncExternalStore(subscribe, getSnapShot, getSnapShot); return state; }; From e6399e20a86be5ae4330b1d5c7c1b30258633495 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 11:18:22 +0100 Subject: [PATCH 102/129] fix --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 046ee6afa5ab8..4a6b6ae84f6d7 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -67,7 +67,7 @@ const getState = ( apiRef: RefObject, refs: RefObject>, listener?: (state: T) => void, -): T => { +) => { const newState = applySelector( apiRef, refs.current.selector, From d4b652be680bcda081c67b1ab6903c49f7547ae0 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 11:27:24 +0100 Subject: [PATCH 103/129] make typescript happy --- .../src/hooks/utils/useGridSelector.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 4a6b6ae84f6d7..e98b8b40201cd 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -63,11 +63,11 @@ type Refs = { argsId: number; }; -const getState = ( +function getState( apiRef: RefObject, refs: RefObject>, - listener?: (state: T) => void, -) => { + callback?: (state: T) => void, +) { const newState = applySelector( apiRef, refs.current.selector, @@ -76,12 +76,16 @@ const getState = ( ) as T; if (!refs.current.equals(refs.current.state, newState)) { refs.current.state = newState; - if (listener) { - listener(newState); + if (callback) { + callback(newState); + return; } } + if (callback) { + return; + } return refs.current.state; -}; +} export const useGridSelector = ( apiRef: RefObject, @@ -111,14 +115,14 @@ export const useGridSelector = ( } const getSnapShot = React.useCallback( - () => getState(apiRef, refs), + () => getState(apiRef, refs)!, // eslint-disable-next-line react-hooks/exhaustive-deps [apiRef, refs.current.argsId], ); const subscribe = React.useCallback( - (listener: (state: T) => void) => - apiRef.current.store.subscribe(() => getState(apiRef, refs, listener)), + (callback: (state: T) => void) => + apiRef.current.store.subscribe(() => getState(apiRef, refs, callback)), // eslint-disable-next-line react-hooks/exhaustive-deps EMPTY, ); From 9f95feef5864fc256014ddd0df23677535e48f79 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 12:52:12 +0100 Subject: [PATCH 104/129] alternative syncexternalstore implementationgetState --- .../src/hooks/utils/useGridSelector.ts | 87 +++++++++++-------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index e98b8b40201cd..c2ea2e016668f 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -50,8 +50,7 @@ export const argsEqual = (prev: any, curr: any) => { return fn(prev, curr); }; -const createRefs = () => - ({ state: null, equals: null, selector: null, args: null, argsId: 0 }) as any; +const createRefs = () => ({ state: null, equals: null, selector: null, args: null }) as any; const EMPTY = [] as unknown[]; @@ -60,32 +59,10 @@ type Refs = { equals: (a: U, b: U) => boolean; selector: Selector; args: any; - argsId: number; + subscription: undefined | (() => void); }; -function getState( - apiRef: RefObject, - refs: RefObject>, - callback?: (state: T) => void, -) { - const newState = applySelector( - apiRef, - refs.current.selector, - refs.current.args, - apiRef.current.instanceId, - ) as T; - if (!refs.current.equals(refs.current.state, newState)) { - refs.current.state = newState; - if (callback) { - callback(newState); - return; - } - } - if (callback) { - return; - } - return refs.current.state; -} +const emptyGetSnapshot = () => null; export const useGridSelector = ( apiRef: RefObject, @@ -105,28 +82,66 @@ export const useGridSelector = ( const refs = useLazyRef, never>(createRefs); const didInit = refs.current.selector !== null; + const [state, setState] = React.useState( + // We don't use an initialization function to avoid allocations + (didInit ? null : applySelector(apiRef, selector, args, apiRef.current.instanceId)) as T, + ); + refs.current.equals = equals; refs.current.selector = selector; const prevArgs = refs.current.args; refs.current.args = args; if (didInit && !argsEqual(prevArgs, args)) { - refs.current.argsId += 1; + const newState = applySelector( + apiRef, + refs.current.selector, + refs.current.args, + apiRef.current.instanceId, + ) as T; + if (!refs.current.equals(refs.current.state, newState)) { + refs.current.state = newState; + setState(newState); + } } - const getSnapShot = React.useCallback( - () => getState(apiRef, refs)!, - // eslint-disable-next-line react-hooks/exhaustive-deps - [apiRef, refs.current.argsId], - ); - const subscribe = React.useCallback( - (callback: (state: T) => void) => - apiRef.current.store.subscribe(() => getState(apiRef, refs, callback)), + () => { + if (refs.current.subscription) { + return null; + } + + refs.current.subscription = apiRef.current.store.subscribe(() => { + const newState = applySelector( + apiRef, + refs.current.selector, + refs.current.args, + apiRef.current.instanceId, + ) as T; + + if (!refs.current.equals(refs.current.state, newState)) { + refs.current.state = newState; + setState(newState); + } + }); + + return null; + }, // eslint-disable-next-line react-hooks/exhaustive-deps EMPTY, ); - const state = useSyncExternalStore(subscribe, getSnapShot, getSnapShot); + const unsubscribe = React.useCallback(() => { + return () => { + if (refs.current.subscription) { + refs.current.subscription(); + refs.current.subscription = undefined; + } + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, EMPTY); + + useSyncExternalStore(unsubscribe, subscribe, emptyGetSnapshot); + return state; }; From 32e4dc2eb34e16c26a84871ea41a263a82d671b1 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 13:16:01 +0100 Subject: [PATCH 105/129] fix --- .../features/cellSelection/useGridCellSelection.ts | 14 +++++++------- .../x-data-grid/src/hooks/utils/useGridSelector.ts | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts b/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts index a1f121c6f31d7..b131c184ac0aa 100644 --- a/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts +++ b/packages/x-data-grid-premium/src/hooks/features/cellSelection/useGridCellSelection.ts @@ -10,7 +10,6 @@ import { isNavigationKey, serializeCellValue, useGridRegisterPipeProcessor, - useGridVisibleRows, } from '@mui/x-data-grid-pro/internals'; import { useGridApiEventHandler, @@ -26,7 +25,6 @@ import { gridFocusCellSelector, GridCellParams, GRID_REORDER_COL_DEF, - useGridSelector, gridSortedRowIdsSelector, gridDimensionsSelector, } from '@mui/x-data-grid-pro'; @@ -64,12 +62,10 @@ export const useGridCellSelection = ( >, ) => { const hasRootReference = apiRef.current.rootElementRef.current !== null; - const visibleRows = useGridVisibleRows(apiRef, props); const cellWithVirtualFocus = React.useRef(null); const lastMouseDownCell = React.useRef(null); const mousePosition = React.useRef<{ x: number; y: number }>(null); const autoScrollRAF = React.useRef(null); - const sortedRowIds = useGridSelector(apiRef, gridSortedRowIdsSelector); const totalHeaderHeight = getTotalHeaderHeight(apiRef, props); const ignoreValueFormatterProp = props.ignoreValueFormatterDuringExport; @@ -144,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); @@ -160,7 +157,7 @@ export const useGridCellSelection = ( apiRef.current.setCellSelectionModel(newModel); }, - [apiRef, visibleRows.rows], + [apiRef], ); const getSelectedCellsAsArray = React.useCallback< @@ -440,6 +437,7 @@ export const useGridCellSelection = ( endColumnIndex -= 1; } + const visibleRows = getVisibleRows(apiRef); if (endRowIndex < 0 || endRowIndex >= visibleRows.rows.length) { return; } @@ -492,6 +490,7 @@ export const useGridCellSelection = ( const addClassesToCells = React.useCallback>( (classes, { id, field }) => { + const visibleRows = getVisibleRows(apiRef); if (!visibleRows.range || !apiRef.current.isCellSelected(id, field)) { return classes; } @@ -540,7 +539,7 @@ export const useGridCellSelection = ( return newClasses; }, - [apiRef, visibleRows.range, visibleRows.rows], + [apiRef], ); const canUpdateFocus = React.useCallback>( @@ -568,6 +567,7 @@ export const useGridCellSelection = ( if (apiRef.current.getSelectedCellsAsArray().length <= 1) { return value; } + const sortedRowIds = gridSortedRowIdsSelector(apiRef.current.state); const cellSelectionModel = apiRef.current.getCellSelectionModel(); const unsortedSelectedRowIds = Object.keys(cellSelectionModel); const sortedSelectedRowIds = sortedRowIds.filter((id) => @@ -596,7 +596,7 @@ export const useGridCellSelection = ( }, ''); return copyData; }, - [apiRef, ignoreValueFormatter, clipboardCopyCellDelimiter, sortedRowIds], + [apiRef, ignoreValueFormatter, clipboardCopyCellDelimiter], ); useGridRegisterPipeProcessor(apiRef, 'isCellSelected', checkIfCellIsSelected); diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index c2ea2e016668f..d8305ce2212ce 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -87,6 +87,7 @@ export const useGridSelector = ( (didInit ? null : applySelector(apiRef, selector, args, apiRef.current.instanceId)) as T, ); + refs.current.state = state; refs.current.equals = equals; refs.current.selector = selector; const prevArgs = refs.current.args; From bae6d9471830380aac8be5cd5b72c2ddb66748ce Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 13:33:59 +0100 Subject: [PATCH 106/129] fix --- packages/x-data-grid/src/hooks/utils/useGridSelector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index d8305ce2212ce..20962d950fbf2 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -50,7 +50,7 @@ export const argsEqual = (prev: any, curr: any) => { return fn(prev, curr); }; -const createRefs = () => ({ state: null, equals: null, selector: null, args: null }) as any; +const createRefs = () => ({ state: null, equals: null, selector: null, args: undefined }) as any; const EMPTY = [] as unknown[]; From cddb1bf4e08fda0cccfa8efdb5a9c77a3cdaca43 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 15:19:34 +0100 Subject: [PATCH 107/129] fuck me --- .../src/hooks/features/dimensions/useGridDimensions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index ef6a55b5bc802..638e052f12a33 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -375,7 +375,6 @@ export function useGridDimensions(apiRef: RefObject, pr function setCSSVariables(root: HTMLElement, dimensions: GridDimensions) { const set = (k: string, v: string) => root.style.setProperty(k, v); - set('--DataGrid-width', `${dimensions.viewportOuterSize.width}px`); set('--DataGrid-hasScrollX', `${Number(dimensions.hasScrollX)}`); set('--DataGrid-hasScrollY', `${Number(dimensions.hasScrollY)}`); set('--DataGrid-scrollbarSize', `${dimensions.scrollbarSize}px`); From 74d77a9ada0b5aaad05c97ec93c612dc1cdbda91 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Fri, 31 Jan 2025 19:09:02 +0100 Subject: [PATCH 108/129] update changelog --- .../migration-data-grid-v7/migration-data-grid-v7.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md index 47f7db8eb4acf..9e986dacc349d 100644 --- a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md +++ b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md @@ -106,6 +106,18 @@ Below are described the steps you need to make to migrate from v7 to v8. +const output = useGridSelector(apiRef, selector, arguments, equals); ``` +- The `filteredRowsLookup` object of the filter state does not contain `true` values anymore. If the row is filtered out, the value is `false`. Otherwise, the row id is not present in the object. + This change only impacts you if you relied on `filteredRowsLookup` to get ids of filtered rows. In this case,use `gridDataRowIdsSelector` selector to get row ids and check `filteredRowsLookup` for `false` values: + + ```diff + -const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); + -const filteredRowIds = Object.keys(filteredRowsLookup).filter((rowId) => filteredRowsLookup[rowId] === true); + + +const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); + +const rowIds = gridDataRowIdsSelector(apiRef); + +const filteredRowIds = rowIds.filter((rowId) => filteredRowsLookup[rowId] !== false); + ``` + ### Other exports - `ariaV8` experimental flag is removed. It's now the default behavior. From e8963ebabeb97bbd2bc66f283b414d754426c56d Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Fri, 31 Jan 2025 19:10:41 +0100 Subject: [PATCH 109/129] update diff --- .../migration-data-grid-v7/migration-data-grid-v7.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md index 9e986dacc349d..14ec2d47e7c83 100644 --- a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md +++ b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md @@ -110,10 +110,8 @@ Below are described the steps you need to make to migrate from v7 to v8. This change only impacts you if you relied on `filteredRowsLookup` to get ids of filtered rows. In this case,use `gridDataRowIdsSelector` selector to get row ids and check `filteredRowsLookup` for `false` values: ```diff - -const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); + const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); -const filteredRowIds = Object.keys(filteredRowsLookup).filter((rowId) => filteredRowsLookup[rowId] === true); - - +const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); +const rowIds = gridDataRowIdsSelector(apiRef); +const filteredRowIds = rowIds.filter((rowId) => filteredRowsLookup[rowId] !== false); ``` From 5d0109bd4d2275c920abcce9d2153e500127a1b5 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 22:19:03 +0100 Subject: [PATCH 110/129] perf: `rowsHeightsChange` event to streamline dimensions/renderContext updates that depend on `rowsMeta.heights` --- .../features/dimensions/useGridDimensions.ts | 13 ++++------- .../hooks/features/rows/useGridRowsMeta.ts | 23 ++++++++++++++----- .../src/models/events/gridEventLookup.ts | 6 +++++ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 638e052f12a33..55fe5ac4aa198 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -100,7 +100,6 @@ export function useGridDimensions(apiRef: RefObject, pr const logger = useGridLogger(apiRef, 'useResizeContainer'); const errorShown = React.useRef(false); const rootDimensionsRef = React.useRef(EMPTY_SIZE); - const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); @@ -140,10 +139,7 @@ export function useGridDimensions(apiRef: RefObject, pr return 0; } - const currentPage = getVisibleRows(apiRef, { - pagination: props.pagination, - paginationMode: props.paginationMode, - }); + const currentPage = getVisibleRows(apiRef); // TODO: Use a combination of scrollTop, dimensions.viewportInnerSize.height and rowsMeta.possitions // to find out the maximum number of rows that can fit in the visible part of the grid @@ -159,7 +155,7 @@ export function useGridDimensions(apiRef: RefObject, pr ); return Math.min(maximumPageSizeWithoutScrollBar, currentPage.rows.length); - }, [apiRef, props.pagination, props.paginationMode, props.getRowHeight, rowHeight]); + }, [apiRef, props.getRowHeight, rowHeight]); const updateDimensions = React.useCallback(() => { if (isFirstSizing.current) { @@ -172,6 +168,7 @@ export function useGridDimensions(apiRef: RefObject, pr const scrollbarSize = measureScrollbarSize(rootElement, props.scrollbarSize); + const rowsMeta = gridRowsMetaSelector(apiRef.current.state); const topContainerHeight = headersTotalHeight + rowsMeta.pinnedTopRowsTotalHeight; const bottomContainerHeight = rowsMeta.pinnedBottomRowsTotalHeight; @@ -282,9 +279,6 @@ export function useGridDimensions(apiRef: RefObject, pr setDimensions, props.scrollbarSize, props.autoHeight, - rowsMeta.currentPageTotalHeight, - rowsMeta.pinnedTopRowsTotalHeight, - rowsMeta.pinnedBottomRowsTotalHeight, rowHeight, headerHeight, groupHeaderHeight, @@ -368,6 +362,7 @@ export function useGridDimensions(apiRef: RefObject, pr [updateDimensions, props.autoHeight, debouncedUpdateDimensions, logger], ); + useGridApiOptionHandler(apiRef, 'rowsHeightsChange', updateDimensions); useGridApiOptionHandler(apiRef, 'rootMount', handleRootMount); useGridApiOptionHandler(apiRef, 'resize', handleResize); useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index c462779d16826..07c5c1cc9fd7a 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -186,18 +186,29 @@ export const useGridRowsMeta = ( lastMeasuredRowIndex.current = Infinity; } + const didHeightsChange = + pinnedTopRowsTotalHeight !== apiRef.current.state.rowsMeta.pinnedTopRowsTotalHeight || + pinnedBottomRowsTotalHeight !== apiRef.current.state.rowsMeta.pinnedBottomRowsTotalHeight || + currentPageTotalHeight !== apiRef.current.state.rowsMeta.currentPageTotalHeight; + + const rowsMeta = { + currentPageTotalHeight, + positions, + pinnedTopRowsTotalHeight, + pinnedBottomRowsTotalHeight, + }; + apiRef.current.setState((state) => { return { ...state, - rowsMeta: { - currentPageTotalHeight, - positions, - pinnedTopRowsTotalHeight, - pinnedBottomRowsTotalHeight, - }, + rowsMeta, }; }); + if (didHeightsChange) { + apiRef.current.publishEvent('rowsHeightsChange', rowsMeta); + } + isHeightMetaValid.current = true; }, [apiRef, pinnedRows, currentPage.rows, processHeightEntry]); diff --git a/packages/x-data-grid/src/models/events/gridEventLookup.ts b/packages/x-data-grid/src/models/events/gridEventLookup.ts index 9f37ed2ede1d4..6bcff7e29f2a1 100644 --- a/packages/x-data-grid/src/models/events/gridEventLookup.ts +++ b/packages/x-data-grid/src/models/events/gridEventLookup.ts @@ -1,4 +1,5 @@ import * as React from 'react'; +import type { GridRowsMetaState } from '../../hooks/features/rows/gridRowsMetaState'; import type { GridColumnHeaderParams, GridColumnOrderChangeParams, @@ -489,6 +490,11 @@ export interface GridEventLookup * Fired when the rendered rows index interval changes. Called with a [[GridRenderContext]] object. */ renderedRowsIntervalChange: { params: GridRenderContext }; + /** + * Fired when the rows total heights change. + * [[GridRowsMetaState]] object. + */ + rowsHeightsChange: { params: GridRowsMetaState }; // Edit /** From 12e0e741a59bcf5ecb85a2986b1820632c9850e4 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Fri, 31 Jan 2025 22:24:06 +0100 Subject: [PATCH 111/129] lint --- docs/data/data-grid/events/events.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/data/data-grid/events/events.json b/docs/data/data-grid/events/events.json index 26bc1b73ed3e6..ed0cfdd7fc37a 100644 --- a/docs/data/data-grid/events/events.json +++ b/docs/data/data-grid/events/events.json @@ -409,6 +409,13 @@ "params": "GridRowSelectionCheckboxParams", "event": "MuiEvent>" }, + { + "projects": ["x-data-grid", "x-data-grid-pro", "x-data-grid-premium"], + "name": "rowsHeightsChange", + "description": "Fired when the rows total heights change. GridRowsMetaState object.", + "params": "GridRowsMetaState", + "event": "MuiEvent<{}>" + }, { "projects": ["x-data-grid-pro", "x-data-grid-premium"], "name": "rowsScrollEnd", From 34497825839833e0ce866797bc8c1b93686197ae Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Fri, 31 Jan 2025 23:19:28 +0100 Subject: [PATCH 112/129] narrow filteredRowsLookup type --- .../features/rowGrouping/gridRowGroupingUtils.ts | 11 ++++++----- .../src/hooks/features/treeData/gridTreeDataUtils.ts | 11 ++++++----- .../src/hooks/features/filter/gridFilterState.ts | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts b/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts index 7e1c99b5f4e2f..846aba5dcfa53 100644 --- a/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts +++ b/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts @@ -1,6 +1,5 @@ import { RefObject } from '@mui/x-internals/types'; import { - GridRowId, GridRowTreeConfig, GridFilterState, GridFilterModel, @@ -80,9 +79,9 @@ export const filterRowTreeFromGroupingColumns = ( params: FilterRowTreeFromTreeDataParams, ): Omit => { const { apiRef, rowTree, isRowMatchingFilters, filterModel } = params; - const filteredRowsLookup: Record = {}; - const filteredChildrenCountLookup: Record = {}; - const filteredDescendantCountLookup: Record = {}; + const filteredRowsLookup: GridFilterState['filteredRowsLookup'] = {}; + const filteredChildrenCountLookup: GridFilterState['filteredChildrenCountLookup'] = {}; + const filteredDescendantCountLookup: GridFilterState['filteredDescendantCountLookup'] = {}; const filterCache = {}; const filterTreeNode = ( @@ -142,7 +141,9 @@ export const filterRowTreeFromGroupingColumns = ( } } - filteredRowsLookup[node.id] = isPassingFiltering; + if (!isPassingFiltering) { + filteredRowsLookup[node.id] = false; + } if (!isPassingFiltering) { return 0; diff --git a/packages/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts b/packages/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts index d3318e53583e5..cbaaee4732b45 100644 --- a/packages/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts +++ b/packages/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts @@ -1,6 +1,5 @@ import { RefObject } from '@mui/x-internals/types'; import { - GridRowId, GridRowTreeConfig, GridTreeNode, GridFilterState, @@ -35,9 +34,9 @@ export const filterRowTreeFromTreeData = ( params: FilterRowTreeFromTreeDataParams, ): Omit => { const { apiRef, rowTree, disableChildrenFiltering, isRowMatchingFilters } = params; - const filteredRowsLookup: Record = {}; - const filteredChildrenCountLookup: Record = {}; - const filteredDescendantCountLookup: Record = {}; + const filteredRowsLookup: GridFilterState['filteredRowsLookup'] = {}; + const filteredChildrenCountLookup: GridFilterState['filteredChildrenCountLookup'] = {}; + const filteredDescendantCountLookup: GridFilterState['filteredDescendantCountLookup'] = {}; const filterCache = {}; const filterResults: GridAggregatedFilterItemApplierResult = { @@ -103,7 +102,9 @@ export const filterRowTreeFromTreeData = ( } } - filteredRowsLookup[node.id] = shouldPassFilters; + if (!shouldPassFilters) { + filteredRowsLookup[node.id] = false; + } if (!shouldPassFilters) { return 0; diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts index f2ae6248584f4..56309a237a177 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts @@ -26,7 +26,7 @@ export interface GridFilterState { * If a row is not registered in this lookup, it is filtered. * This is the equivalent of the `visibleRowsLookup` if all the groups were expanded. */ - filteredRowsLookup: Record; + filteredRowsLookup: Record; /** * Amount of children that are passing the filters or have children that are passing the filter (does not count grand children). * If a row is not registered in this lookup, it is supposed to have no descendant passing the filters. From 26be717198ad5419b6bff570d0d5a7f34c144456 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sat, 1 Feb 2025 01:25:00 +0100 Subject: [PATCH 113/129] fix --- packages/x-data-grid-pro/src/utils/tree/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid-pro/src/utils/tree/utils.ts b/packages/x-data-grid-pro/src/utils/tree/utils.ts index fba2f4c9bfa23..0bb0f960d9a87 100644 --- a/packages/x-data-grid-pro/src/utils/tree/utils.ts +++ b/packages/x-data-grid-pro/src/utils/tree/utils.ts @@ -243,7 +243,7 @@ export const getVisibleRowsLookup = ({ const visibleRowsLookup: Record = {}; const handleTreeNode = (node: GridTreeNode, areAncestorsExpanded: boolean) => { - const isPassingFiltering = filteredRowsLookup[node.id]; + const isPassingFiltering = filteredRowsLookup[node.id] !== false; if (node.type === 'group') { node.children.forEach((childId) => { From b4ab00c722c6696d6c981e49d548b25c3cfd9273 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sat, 1 Feb 2025 11:29:19 +0100 Subject: [PATCH 114/129] fix --- packages/x-data-grid/src/hooks/features/rowSelection/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/rowSelection/utils.ts b/packages/x-data-grid/src/hooks/features/rowSelection/utils.ts index 76dacf2c0cd5b..91e2323e91507 100644 --- a/packages/x-data-grid/src/hooks/features/rowSelection/utils.ts +++ b/packages/x-data-grid/src/hooks/features/rowSelection/utils.ts @@ -145,7 +145,7 @@ const getFilteredRowNodeSiblings = ( const parentNode = tree[parent] as GridGroupNode; - return parentNode.children.filter((childId) => childId !== id && filteredRows[childId]); + return parentNode.children.filter((childId) => childId !== id && filteredRows[childId] !== false); }; export const findRowsToSelect = ( From eb577a3b0c5769a59d471b1e945dfef341590fc4 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sat, 1 Feb 2025 14:06:18 +0100 Subject: [PATCH 115/129] fix detailpanel --- docs/data/data-grid/events/events.json | 7 ------- .../detailPanel/useGridDetailPanel.ts | 19 +++++++------------ .../tests/detailPanel.DataGridPro.test.tsx | 14 +++++++++----- .../useGridRegisterPipeProcessor.ts | 9 ++++++--- .../features/dimensions/useGridDimensions.ts | 1 - .../hooks/features/rows/useGridRowsMeta.ts | 2 +- .../src/models/events/gridEventLookup.ts | 6 ------ .../useResizeObserver/useResizeObserver.ts | 2 +- 8 files changed, 24 insertions(+), 36 deletions(-) diff --git a/docs/data/data-grid/events/events.json b/docs/data/data-grid/events/events.json index ed0cfdd7fc37a..26bc1b73ed3e6 100644 --- a/docs/data/data-grid/events/events.json +++ b/docs/data/data-grid/events/events.json @@ -409,13 +409,6 @@ "params": "GridRowSelectionCheckboxParams", "event": "MuiEvent>" }, - { - "projects": ["x-data-grid", "x-data-grid-pro", "x-data-grid-premium"], - "name": "rowsHeightsChange", - "description": "Fired when the rows total heights change. GridRowsMetaState object.", - "params": "GridRowsMetaState", - "event": "MuiEvent<{}>" - }, { "projects": ["x-data-grid-pro", "x-data-grid-premium"], "name": "rowsScrollEnd", diff --git a/packages/x-data-grid-pro/src/hooks/features/detailPanel/useGridDetailPanel.ts b/packages/x-data-grid-pro/src/hooks/features/detailPanel/useGridDetailPanel.ts index 2d0c2cea43287..27dfcc350ca94 100644 --- a/packages/x-data-grid-pro/src/hooks/features/detailPanel/useGridDetailPanel.ts +++ b/packages/x-data-grid-pro/src/hooks/features/detailPanel/useGridDetailPanel.ts @@ -28,9 +28,6 @@ import { GridDetailPanelState, } from './gridDetailPanelInterface'; -// FIXME: calling `api.updateDimensions()` here triggers a cycle where `updateDimensions` is -// called 3 times when opening/closing a panel. - const emptySet = new Set(); export const detailPanelStateInitializer: GridStateInitializer< @@ -179,8 +176,6 @@ export const useGridDetailPanel = ( }, }; }); - apiRef.current.updateDimensions(); - apiRef.current.forceUpdate(); }, [apiRef], ); @@ -204,7 +199,6 @@ export const useGridDetailPanel = ( }, }; }); - apiRef.current.updateDimensions(); apiRef.current.requestPipeProcessorsApplication('rowHeight'); }, @@ -234,6 +228,9 @@ export const useGridDetailPanel = ( }, [apiRef, props.detailPanelExpandedRowIds]); const updateCachesAndForceUpdate = React.useCallback(() => { + if (!props.getDetailPanelContent) { + return; + } apiRef.current.setState((state) => { return { ...state, @@ -248,16 +245,15 @@ export const useGridDetailPanel = ( }, }; }); - apiRef.current.updateDimensions?.(); apiRef.current.forceUpdate(); }, [apiRef, props.getDetailPanelContent, props.getDetailPanelHeight]); useGridApiEventHandler(apiRef, 'sortedRowsSet', updateCachesAndForceUpdate); const previousGetDetailPanelContentProp = - React.useRef(null); + React.useRef(undefined); const previousGetDetailPanelHeightProp = - React.useRef(null); + React.useRef(undefined); const updateCachesIfNeeded = React.useCallback(() => { if ( @@ -281,7 +277,6 @@ export const useGridDetailPanel = ( }, }; }); - apiRef.current.updateDimensions?.(); previousGetDetailPanelContentProp.current = props.getDetailPanelContent; previousGetDetailPanelHeightProp.current = props.getDetailPanelHeight; @@ -304,7 +299,8 @@ export const useGridDetailPanel = ( [apiRef, expandedRowIds, updateCachesIfNeeded], ); - useGridRegisterPipeProcessor(apiRef, 'rowHeight', addDetailHeight); + const enabled = props.getDetailPanelContent !== undefined; + useGridRegisterPipeProcessor(apiRef, 'rowHeight', addDetailHeight, enabled); const isFirstRender = React.useRef(true); if (isFirstRender.current) { @@ -313,7 +309,6 @@ export const useGridDetailPanel = ( React.useEffect(() => { if (!isFirstRender.current) { updateCachesIfNeeded(); - apiRef.current.hydrateRowsMeta(); } isFirstRender.current = false; }, [apiRef, updateCachesIfNeeded]); diff --git a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx index b674feba8ef9e..3ed9018d5dc53 100644 --- a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx @@ -20,7 +20,7 @@ import { act, reactMajor, } from '@mui/internal-test-utils'; -import { $, $$, grid, getRow, getCell, getColumnValues, microtasks } from 'test/utils/helperFn'; +import { $, $$, grid, getRow, getCell, getColumnValues } from 'test/utils/helperFn'; import { fireUserEvent } from 'test/utils/fireUserEvent'; import { testSkipIf, isJSDOM } from 'test/utils/skipIf'; @@ -83,7 +83,7 @@ describe(' - Detail panel', () => { async () => { const rowHeight = 50; const detailPanelHeight = 100; - render( + const { user } = render( - Detail panel', () => { getDetailPanelHeight={() => 'auto'} />, ); - fireEvent.click(screen.getAllByRole('button', { name: 'Expand' })[0]); - await microtasks(); + await user.click(screen.getAllByRole('button', { name: 'Expand' })[0]); + await waitFor(() => + expect(getRow(0).className).to.include(gridClasses['row--detailPanelExpanded']), + ); const virtualScrollerContent = $('.MuiDataGrid-virtualScrollerContent')!; expect(virtualScrollerContent).toHaveComputedStyle({ @@ -133,7 +135,9 @@ describe(' - Detail panel', () => { const virtualScrollerContent = grid('virtualScrollerContent')!; await user.click(screen.getByRole('button', { name: 'Expand' })); - expect(getRow(0).className).to.include(gridClasses['row--detailPanelExpanded']); + await waitFor(() => + expect(getRow(0).className).to.include(gridClasses['row--detailPanelExpanded']), + ); expect(virtualScrollerContent).toHaveComputedStyle({ height: `${rowHeight + 100}px` }); expect(virtualScrollerContent).toHaveInlineStyle({ width: 'auto' }); diff --git a/packages/x-data-grid/src/hooks/core/pipeProcessing/useGridRegisterPipeProcessor.ts b/packages/x-data-grid/src/hooks/core/pipeProcessing/useGridRegisterPipeProcessor.ts index d15fa6077945a..ec918959da3cd 100644 --- a/packages/x-data-grid/src/hooks/core/pipeProcessing/useGridRegisterPipeProcessor.ts +++ b/packages/x-data-grid/src/hooks/core/pipeProcessing/useGridRegisterPipeProcessor.ts @@ -11,6 +11,7 @@ export const useGridRegisterPipeProcessor = < apiRef: RefObject, group: G, callback: GridPipeProcessor, + enabled: boolean = true, ) => { const cleanup = React.useRef<(() => void) | null>(null); const id = React.useRef(`mui-${Math.round(Math.random() * 1e9)}`); @@ -20,14 +21,16 @@ export const useGridRegisterPipeProcessor = < }, [apiRef, callback, group]); useFirstRender(() => { - registerPreProcessor(); + if (enabled) { + registerPreProcessor(); + } }); const isFirstRender = React.useRef(true); React.useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; - } else { + } else if (enabled) { registerPreProcessor(); } @@ -37,5 +40,5 @@ export const useGridRegisterPipeProcessor = < cleanup.current = null; } }; - }, [registerPreProcessor]); + }, [registerPreProcessor, enabled]); }; diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 55fe5ac4aa198..11ea5dda032b2 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -362,7 +362,6 @@ export function useGridDimensions(apiRef: RefObject, pr [updateDimensions, props.autoHeight, debouncedUpdateDimensions, logger], ); - useGridApiOptionHandler(apiRef, 'rowsHeightsChange', updateDimensions); useGridApiOptionHandler(apiRef, 'rootMount', handleRootMount); useGridApiOptionHandler(apiRef, 'resize', handleResize); useGridApiOptionHandler(apiRef, 'debouncedResize', props.onResize); diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 07c5c1cc9fd7a..70b4cf19a6359 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -206,7 +206,7 @@ export const useGridRowsMeta = ( }); if (didHeightsChange) { - apiRef.current.publishEvent('rowsHeightsChange', rowsMeta); + apiRef.current.updateDimensions(); } isHeightMetaValid.current = true; diff --git a/packages/x-data-grid/src/models/events/gridEventLookup.ts b/packages/x-data-grid/src/models/events/gridEventLookup.ts index 6bcff7e29f2a1..9f37ed2ede1d4 100644 --- a/packages/x-data-grid/src/models/events/gridEventLookup.ts +++ b/packages/x-data-grid/src/models/events/gridEventLookup.ts @@ -1,5 +1,4 @@ import * as React from 'react'; -import type { GridRowsMetaState } from '../../hooks/features/rows/gridRowsMetaState'; import type { GridColumnHeaderParams, GridColumnOrderChangeParams, @@ -490,11 +489,6 @@ export interface GridEventLookup * Fired when the rendered rows index interval changes. Called with a [[GridRenderContext]] object. */ renderedRowsIntervalChange: { params: GridRenderContext }; - /** - * Fired when the rows total heights change. - * [[GridRowsMetaState]] object. - */ - rowsHeightsChange: { params: GridRowsMetaState }; // Edit /** diff --git a/packages/x-internals/src/useResizeObserver/useResizeObserver.ts b/packages/x-internals/src/useResizeObserver/useResizeObserver.ts index 19e4d5bb89a19..452ece1dbe34a 100644 --- a/packages/x-internals/src/useResizeObserver/useResizeObserver.ts +++ b/packages/x-internals/src/useResizeObserver/useResizeObserver.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils'; -const isDevEnvironment = process.env.NODE_ENV === 'development'; +const isDevEnvironment = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test'; const noop = () => {}; From d6288816de3261422588140b63a376cefc2d7dba Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sat, 1 Feb 2025 23:30:55 +0100 Subject: [PATCH 116/129] remove some newly introduced selectors --- .../src/components/GridPinnedRows.tsx | 8 ++- .../src/components/GridScrollArea.tsx | 52 +++++++++++-------- .../virtualization/GridVirtualScroller.tsx | 24 +++------ .../hooks/features/rows/gridRowsSelector.ts | 16 ------ .../virtualization/useGridVirtualScroller.tsx | 18 +++++-- 5 files changed, 54 insertions(+), 64 deletions(-) diff --git a/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx b/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx index 04dfb4ccd17c5..d839455b4b181 100644 --- a/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx +++ b/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx @@ -5,7 +5,6 @@ import { getDataGridUtilityClass, gridClasses, useGridSelector } from '@mui/x-da import { GridPinnedRowsProps, gridPinnedRowsSelector, - gridRenderContextSelector, useGridPrivateApiContext, } from '@mui/x-data-grid/internals'; @@ -20,7 +19,6 @@ 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]; @@ -28,10 +26,10 @@ export function GridPinnedRows({ position, virtualScroller }: GridPinnedRowsProp () => ({ firstRowIndex: 0, lastRowIndex: rows.length, - firstColumnIndex: renderContext.firstColumnIndex, - lastColumnIndex: renderContext.lastColumnIndex, + firstColumnIndex: undefined, + lastColumnIndex: undefined, }), - [rows, renderContext.firstColumnIndex, renderContext.lastColumnIndex], + [rows], ); if (rows.length === 0) { diff --git a/packages/x-data-grid/src/components/GridScrollArea.tsx b/packages/x-data-grid/src/components/GridScrollArea.tsx index 47efdb7d773d8..782814ffb0432 100644 --- a/packages/x-data-grid/src/components/GridScrollArea.tsx +++ b/packages/x-data-grid/src/components/GridScrollArea.tsx @@ -7,6 +7,7 @@ import { } from '@mui/utils'; import { styled } from '@mui/system'; import { fastMemo } from '@mui/x-internals/fastMemo'; +import { RefObject } from '@mui/x-internals/types'; import { DataGridProcessedProps } from '../models/props/DataGridProps'; import { useGridRootProps } from '../hooks/utils/useGridRootProps'; import { getDataGridUtilityClass, gridClasses } from '../constants'; @@ -27,6 +28,7 @@ const SLOP = 1.5; interface ScrollAreaProps { scrollDirection: 'left' | 'right'; + scrollPosition: RefObject; } type OwnerState = DataGridProcessedProps & Pick; @@ -76,8 +78,30 @@ const offsetSelector = createSelector( }, ); -function GridScrollAreaRaw(props: ScrollAreaProps) { - const { scrollDirection } = props; +function GridScrollAreaWrapper(props: ScrollAreaProps) { + const apiRef = useGridApiContext(); + const [dragging, setDragging] = React.useState(false); + + const handleColumnHeaderDragStart = useEventCallback(() => { + setDragging(true); + }); + + const handleColumnHeaderDragEnd = useEventCallback(() => { + setDragging(false); + }); + + useGridApiEventHandler(apiRef, 'columnHeaderDragStart', handleColumnHeaderDragStart); + useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', handleColumnHeaderDragEnd); + + if (!dragging) { + return null; + } + + return ; +} + +function GridScrollAreaContent(props: ScrollAreaProps) { + const { scrollDirection, scrollPosition } = props; const rootRef = React.useRef(null); const apiRef = useGridApiContext(); const timeout = useTimeout(); @@ -85,11 +109,6 @@ function GridScrollAreaRaw(props: ScrollAreaProps) { const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); const sideOffset = useGridSelector(apiRef, offsetSelector, scrollDirection); - const scrollPosition = React.useRef({ - left: 0, - top: 0, - }); - const getCanScrollMore = () => { const dimensions = gridDimensionsSelector(apiRef.current.state); if (scrollDirection === 'left') { @@ -106,7 +125,6 @@ function GridScrollAreaRaw(props: ScrollAreaProps) { return false; }; - const [dragging, setDragging] = React.useState(false); const [canScrollMore, setCanScrollMore] = React.useState(getCanScrollMore); const rootProps = useGridRootProps(); @@ -126,9 +144,7 @@ function GridScrollAreaRaw(props: ScrollAreaProps) { style.right = sideOffset; } - const handleScrolling: GridEventListener<'scrollPositionChange'> = (newScrollPosition) => { - scrollPosition.current = newScrollPosition; - + const handleScrolling: GridEventListener<'scrollPositionChange'> = () => { setCanScrollMore(getCanScrollMore); }; @@ -157,19 +173,9 @@ function GridScrollAreaRaw(props: ScrollAreaProps) { }); }); - const handleColumnHeaderDragStart = useEventCallback(() => { - setDragging(true); - }); - - const handleColumnHeaderDragEnd = useEventCallback(() => { - setDragging(false); - }); - useGridApiEventHandler(apiRef, 'scrollPositionChange', handleScrolling); - useGridApiEventHandler(apiRef, 'columnHeaderDragStart', handleColumnHeaderDragStart); - useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', handleColumnHeaderDragEnd); - if (!dragging || !canScrollMore) { + if (!canScrollMore) { return null; } @@ -184,4 +190,4 @@ function GridScrollAreaRaw(props: ScrollAreaProps) { ); } -export const GridScrollArea = fastMemo(GridScrollAreaRaw); +export const GridScrollArea = fastMemo(GridScrollAreaWrapper); diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index 82e96d19e0446..a1c3b96c20470 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -24,10 +24,6 @@ import { GridVirtualScrollerRenderZone as RenderZone } from './GridVirtualScroll import { GridVirtualScrollbar as Scrollbar } from './GridVirtualScrollbar'; import { GridLoadingOverlayVariant } from '../GridLoadingOverlay'; import { GridStateCommunity } from '../../models/gridStateCommunity'; -import { - gridHasBottomPinnedRowsSelector, - gridHasTopPinnedRowsSelector, -} from '../../hooks/features/rows/gridRowsSelector'; type OwnerState = Pick & { hasScrollX: boolean; @@ -87,8 +83,6 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { const rootProps = useGridRootProps(); const hasScrollY = useGridSelector(apiRef, gridHasScrollYSelector); const hasScrollX = useGridSelector(apiRef, gridHasScrollXSelector); - const hasTopPinnedRows = useGridSelector(apiRef, gridHasTopPinnedRowsSelector); - const hasBottomPinnedRows = useGridSelector(apiRef, gridHasBottomPinnedRowsSelector); const hasPinnedRight = useGridSelector(apiRef, hasPinnedRightSelector); const hasBottomFiller = useGridSelector(apiRef, gridHasBottomFillerSelector); const { getOverlay, overlaysProps } = useGridOverlays(); @@ -109,20 +103,19 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { getScrollbarVerticalProps, getScrollbarHorizontalProps, getRows, + getScrollAreaProps, } = virtualScroller; const rows = getRows(); return ( - - + + {!rootProps.unstable_listView && } - {hasTopPinnedRows && ( - - )} + {getOverlay()} @@ -135,12 +128,9 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { {hasBottomFiller && } - - {hasBottomPinnedRows && ( - - - - )} + + + {hasScrollX && !rootProps.unstable_listView && ( diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts index 1c703eac2ef78..2cfb32ed68156 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts @@ -95,22 +95,6 @@ export const gridPinnedRowsSelector = createSelectorMemoized( }, ); -/** - * @ignore - do not document. - */ -export const gridHasTopPinnedRowsSelector = createSelectorMemoized( - gridAdditionalRowGroupsSelector, - (additionalRowGroups) => Boolean(additionalRowGroups?.pinnedRows?.top?.length), -); - -/** - * @ignore - do not document. - */ -export const gridHasBottomPinnedRowsSelector = createSelectorMemoized( - gridAdditionalRowGroupsSelector, - (additionalRowGroups) => Boolean(additionalRowGroups?.pinnedRows?.bottom?.length), -); - /** * @ignore - do not document. */ diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index bf77fe7dd319d..5e35ccaa91b1d 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -398,14 +398,24 @@ export const useGridVirtualScroller = () => { params: { rows?: GridRowEntry[]; position?: GridPinnedRowsPosition; - renderContext?: GridRenderContext; + renderContext?: + | GridRenderContext + | (Pick & { + firstColumnIndex: undefined; + lastColumnIndex: undefined; + }); } = {}, ) => { if (!params.rows && !currentPage.range) { return []; } - const baseRenderContext = params.renderContext ?? renderContext; + let baseRenderContext = renderContext; + if (params.renderContext) { + baseRenderContext = params.renderContext as GridRenderContext; + baseRenderContext.firstColumnIndex = renderContext.firstColumnIndex; + baseRenderContext.lastColumnIndex = renderContext.lastColumnIndex; + } const isLastSection = (!hasBottomPinnedRows && params.position === undefined) || @@ -520,7 +530,6 @@ export const useGridVirtualScroller = () => { let currentRenderContext = baseRenderContext; if ( - !isPinnedSection && frozenContext.current && rowIndexInPage >= frozenContext.current.firstRowIndex && rowIndexInPage < frozenContext.current.lastRowIndex @@ -731,6 +740,9 @@ export const useGridVirtualScroller = () => { role: 'presentation', scrollPosition, }), + getScrollAreaProps: () => ({ + scrollPosition, + }), }; }; From 9760a27fece64d45569dedf40095de4c28a2e679 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sat, 1 Feb 2025 23:47:48 +0100 Subject: [PATCH 117/129] column render context override --- .../features/virtualization/useGridVirtualScroller.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 5e35ccaa91b1d..f29981eaab498 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -413,8 +413,13 @@ export const useGridVirtualScroller = () => { let baseRenderContext = renderContext; if (params.renderContext) { baseRenderContext = params.renderContext as GridRenderContext; - baseRenderContext.firstColumnIndex = renderContext.firstColumnIndex; - baseRenderContext.lastColumnIndex = renderContext.lastColumnIndex; + if ( + baseRenderContext.firstColumnIndex === undefined || + baseRenderContext.lastColumnIndex === undefined + ) { + baseRenderContext.firstColumnIndex = renderContext.firstColumnIndex; + baseRenderContext.lastColumnIndex = renderContext.lastColumnIndex; + } } const isLastSection = From 700536632b44522d793710a2ae2802cf9cf9e255 Mon Sep 17 00:00:00 2001 From: lauri865 Date: Sun, 2 Feb 2025 00:17:02 +0100 Subject: [PATCH 118/129] revert --- .../features/virtualization/useGridVirtualScroller.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index f29981eaab498..1d1ba9ea126b0 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -413,13 +413,9 @@ export const useGridVirtualScroller = () => { let baseRenderContext = renderContext; if (params.renderContext) { baseRenderContext = params.renderContext as GridRenderContext; - if ( - baseRenderContext.firstColumnIndex === undefined || - baseRenderContext.lastColumnIndex === undefined - ) { - baseRenderContext.firstColumnIndex = renderContext.firstColumnIndex; - baseRenderContext.lastColumnIndex = renderContext.lastColumnIndex; - } + + baseRenderContext.firstColumnIndex = renderContext.firstColumnIndex; + baseRenderContext.lastColumnIndex = renderContext.lastColumnIndex; } const isLastSection = From af40788305de53070f9d49665e35748e7f5a47f5 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Mon, 3 Feb 2025 13:35:50 +0100 Subject: [PATCH 119/129] narrow visibleRowsLookup type --- packages/x-data-grid-pro/src/utils/tree/utils.ts | 14 ++++++++++---- .../src/hooks/features/filter/gridFilterState.ts | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/x-data-grid-pro/src/utils/tree/utils.ts b/packages/x-data-grid-pro/src/utils/tree/utils.ts index 0bb0f960d9a87..0e79df66cc14c 100644 --- a/packages/x-data-grid-pro/src/utils/tree/utils.ts +++ b/packages/x-data-grid-pro/src/utils/tree/utils.ts @@ -16,6 +16,7 @@ import { } from '@mui/x-data-grid/internals'; import { RowTreeBuilderGroupingCriterion } from './models'; import { DataGridProProps } from '../../models/dataGridProProps'; +import type { GridStatePro } from '../../models/gridStatePro'; export const getGroupRowIdFromPath = (path: RowTreeBuilderGroupingCriterion[]) => { const pathStr = path @@ -240,7 +241,7 @@ export const getVisibleRowsLookup = ({ return {}; } - const visibleRowsLookup: Record = {}; + const visibleRowsLookup: GridStatePro['visibleRowsLookup'] = {}; const handleTreeNode = (node: GridTreeNode, areAncestorsExpanded: boolean) => { const isPassingFiltering = filteredRowsLookup[node.id] !== false; @@ -252,12 +253,17 @@ export const getVisibleRowsLookup = ({ }); } - visibleRowsLookup[node.id] = isPassingFiltering && areAncestorsExpanded; + const isVisible = isPassingFiltering && areAncestorsExpanded; + if (!isVisible) { + visibleRowsLookup[node.id] = isVisible; + } // TODO rows v6: Should we keep storing the visibility status of footer independently or rely on the group visibility in the selector ? if (node.type === 'group' && node.footerId != null) { - visibleRowsLookup[node.footerId] = - isPassingFiltering && areAncestorsExpanded && !!node.childrenExpanded; + const isFooterVisible = isPassingFiltering && areAncestorsExpanded && !!node.childrenExpanded; + if (!isFooterVisible) { + visibleRowsLookup[node.footerId] = isFooterVisible; + } } }; diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts index 56309a237a177..50daedd072695 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts @@ -73,4 +73,4 @@ export type GridFilteringMethodValue = Omit; * A row is visible if it is passing the filters AND if its parents are expanded. * If a row is not registered in this lookup, it is visible. */ -export type GridVisibleRowsLookupState = Record; +export type GridVisibleRowsLookupState = Record; From 0b6bcda48aa24f44908e1ff9fd5eee794b175f9e Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Mon, 3 Feb 2025 13:39:31 +0100 Subject: [PATCH 120/129] update changelog --- .../migration-data-grid-v7/migration-data-grid-v7.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md index 14ec2d47e7c83..5ba9f9de3cb23 100644 --- a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md +++ b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md @@ -116,6 +116,13 @@ Below are described the steps you need to make to migrate from v7 to v8. +const filteredRowIds = rowIds.filter((rowId) => filteredRowsLookup[rowId] !== false); ``` +- The `visibleRowsLookup` state does not contain `true` values anymore. If the row is not visible, the value is `false`. Otherwise, the row id is not present in the object: + ```diff + const visibleRowsLookup = gridVisibleRowsLookupSelector(apiRef); + -const isRowVisible = visibleRowsLookup[rowId] === true; + +const isRowVisible = visibleRowsLookup[rowId] !== false; + ``` + ### Other exports - `ariaV8` experimental flag is removed. It's now the default behavior. From 676da6b06af9a81646c6e015f1e3486a0567c7ba Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Tue, 4 Feb 2025 00:18:28 +0100 Subject: [PATCH 121/129] useEventCallback --- .../src/hooks/utils/useGridSelector.ts | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 20962d950fbf2..0a68f57f39613 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -3,6 +3,7 @@ import { RefObject } from '@mui/x-internals/types'; import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare'; import { warnOnce } from '@mui/x-internals/warning'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; +import { unstable_useEventCallback as useEventCallback } from '@mui/utils'; import type { GridApiCommon } from '../../models/api/gridApiCommon'; import type { OutputSelector } from '../../utils/createSelector'; import { useLazyRef } from './useLazyRef'; @@ -52,8 +53,6 @@ export const argsEqual = (prev: any, curr: any) => { const createRefs = () => ({ state: null, equals: null, selector: null, args: undefined }) as any; -const EMPTY = [] as unknown[]; - type Refs = { state: T; equals: (a: U, b: U) => boolean; @@ -106,41 +105,36 @@ export const useGridSelector = ( } } - const subscribe = React.useCallback( - () => { - if (refs.current.subscription) { - return null; - } - - refs.current.subscription = apiRef.current.store.subscribe(() => { - const newState = applySelector( - apiRef, - refs.current.selector, - refs.current.args, - apiRef.current.instanceId, - ) as T; + const subscribe = useEventCallback(() => { + if (refs.current.subscription) { + return null; + } - if (!refs.current.equals(refs.current.state, newState)) { - refs.current.state = newState; - setState(newState); - } - }); + refs.current.subscription = apiRef.current.store.subscribe(() => { + const newState = applySelector( + apiRef, + refs.current.selector, + refs.current.args, + apiRef.current.instanceId, + ) as T; + + if (!refs.current.equals(refs.current.state, newState)) { + refs.current.state = newState; + setState(newState); + } + }); - return null; - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - EMPTY, - ); + return null; + }); - const unsubscribe = React.useCallback(() => { + const unsubscribe = useEventCallback(() => { return () => { if (refs.current.subscription) { refs.current.subscription(); refs.current.subscription = undefined; } }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, EMPTY); + }); useSyncExternalStore(unsubscribe, subscribe, emptyGetSnapshot); From f8ca72688d1bc2dcb3d01921bab28f240af4a02b Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Tue, 4 Feb 2025 10:18:37 +0100 Subject: [PATCH 122/129] Revert "useEventCallback" This reverts commit 676da6b06af9a81646c6e015f1e3486a0567c7ba. --- .../src/hooks/utils/useGridSelector.ts | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts index 0a68f57f39613..20962d950fbf2 100644 --- a/packages/x-data-grid/src/hooks/utils/useGridSelector.ts +++ b/packages/x-data-grid/src/hooks/utils/useGridSelector.ts @@ -3,7 +3,6 @@ import { RefObject } from '@mui/x-internals/types'; import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare'; import { warnOnce } from '@mui/x-internals/warning'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; -import { unstable_useEventCallback as useEventCallback } from '@mui/utils'; import type { GridApiCommon } from '../../models/api/gridApiCommon'; import type { OutputSelector } from '../../utils/createSelector'; import { useLazyRef } from './useLazyRef'; @@ -53,6 +52,8 @@ export const argsEqual = (prev: any, curr: any) => { const createRefs = () => ({ state: null, equals: null, selector: null, args: undefined }) as any; +const EMPTY = [] as unknown[]; + type Refs = { state: T; equals: (a: U, b: U) => boolean; @@ -105,36 +106,41 @@ export const useGridSelector = ( } } - const subscribe = useEventCallback(() => { - if (refs.current.subscription) { - return null; - } - - refs.current.subscription = apiRef.current.store.subscribe(() => { - const newState = applySelector( - apiRef, - refs.current.selector, - refs.current.args, - apiRef.current.instanceId, - ) as T; - - if (!refs.current.equals(refs.current.state, newState)) { - refs.current.state = newState; - setState(newState); + const subscribe = React.useCallback( + () => { + if (refs.current.subscription) { + return null; } - }); - return null; - }); + refs.current.subscription = apiRef.current.store.subscribe(() => { + const newState = applySelector( + apiRef, + refs.current.selector, + refs.current.args, + apiRef.current.instanceId, + ) as T; + + if (!refs.current.equals(refs.current.state, newState)) { + refs.current.state = newState; + setState(newState); + } + }); + + return null; + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + EMPTY, + ); - const unsubscribe = useEventCallback(() => { + const unsubscribe = React.useCallback(() => { return () => { if (refs.current.subscription) { refs.current.subscription(); refs.current.subscription = undefined; } }; - }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, EMPTY); useSyncExternalStore(unsubscribe, subscribe, emptyGetSnapshot); From 1c5e1d21a26aca043557fa8e1a5165d59181a7a7 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Wed, 5 Feb 2025 12:37:11 +0100 Subject: [PATCH 123/129] avoid changing object shape --- packages/x-data-grid-pro/src/components/GridPinnedRows.tsx | 4 ++-- .../features/virtualization/useGridVirtualScroller.tsx | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx b/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx index d839455b4b181..7a7451f6520f9 100644 --- a/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx +++ b/packages/x-data-grid-pro/src/components/GridPinnedRows.tsx @@ -26,8 +26,8 @@ export function GridPinnedRows({ position, virtualScroller }: GridPinnedRowsProp () => ({ firstRowIndex: 0, lastRowIndex: rows.length, - firstColumnIndex: undefined, - lastColumnIndex: undefined, + firstColumnIndex: -1, + lastColumnIndex: -1, }), [rows], ); diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 1d1ba9ea126b0..aa508c0306e35 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -398,12 +398,7 @@ export const useGridVirtualScroller = () => { params: { rows?: GridRowEntry[]; position?: GridPinnedRowsPosition; - renderContext?: - | GridRenderContext - | (Pick & { - firstColumnIndex: undefined; - lastColumnIndex: undefined; - }); + renderContext?: GridRenderContext; } = {}, ) => { if (!params.rows && !currentPage.range) { From 9708bf1e05a698b1cefc8a7cf5ca37090670c2f7 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Wed, 5 Feb 2025 12:39:13 +0100 Subject: [PATCH 124/129] update jsdoc --- .../x-data-grid/src/hooks/features/filter/gridFilterState.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts index 50daedd072695..4a6fb5d892e67 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterState.ts @@ -23,7 +23,7 @@ export interface GridFilterState { /** * Filtering status for each row. * A row is filtered if it is passing the filters, whether its parents are expanded or not. - * If a row is not registered in this lookup, it is filtered. + * All the rows are filtered except the ones registered in this lookup with `false` values. * This is the equivalent of the `visibleRowsLookup` if all the groups were expanded. */ filteredRowsLookup: Record; From c0f1205e39fcaea34f53d8e1024ff6df15fcf37b Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Wed, 5 Feb 2025 13:08:22 +0100 Subject: [PATCH 125/129] remove unnecessary useEventCallback --- .../x-data-grid/src/components/GridScrollArea.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/x-data-grid/src/components/GridScrollArea.tsx b/packages/x-data-grid/src/components/GridScrollArea.tsx index 782814ffb0432..461cde87c7e86 100644 --- a/packages/x-data-grid/src/components/GridScrollArea.tsx +++ b/packages/x-data-grid/src/components/GridScrollArea.tsx @@ -82,16 +82,8 @@ function GridScrollAreaWrapper(props: ScrollAreaProps) { const apiRef = useGridApiContext(); const [dragging, setDragging] = React.useState(false); - const handleColumnHeaderDragStart = useEventCallback(() => { - setDragging(true); - }); - - const handleColumnHeaderDragEnd = useEventCallback(() => { - setDragging(false); - }); - - useGridApiEventHandler(apiRef, 'columnHeaderDragStart', handleColumnHeaderDragStart); - useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', handleColumnHeaderDragEnd); + useGridApiEventHandler(apiRef, 'columnHeaderDragStart', () => setDragging(true)); + useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', () => setDragging(false)); if (!dragging) { return null; From 6bbf36d098507910d3076cc423ab1c0d940b19d2 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Wed, 5 Feb 2025 13:18:52 +0100 Subject: [PATCH 126/129] move dimensions selectors to feature folder --- .../src/components/GridScrollArea.tsx | 6 ++- .../components/GridSkeletonLoadingOverlay.tsx | 2 +- .../virtualization/GridVirtualScroller.tsx | 2 +- .../columnHeaders/useGridColumnHeaders.tsx | 2 +- .../dimensions/gridDimensionsSelectors.ts | 42 ++++++++++++++++++ .../src/hooks/features/dimensions/index.ts | 2 +- .../hooks/features/rows/useGridRowsMeta.ts | 6 ++- .../virtualization/useGridVirtualScroller.tsx | 4 +- packages/x-data-grid/src/internals/index.ts | 3 +- .../internals/selectors/dimensionSelectors.ts | 43 ------------------- 10 files changed, 57 insertions(+), 55 deletions(-) delete mode 100644 packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts diff --git a/packages/x-data-grid/src/components/GridScrollArea.tsx b/packages/x-data-grid/src/components/GridScrollArea.tsx index 461cde87c7e86..c4286ff8c22b2 100644 --- a/packages/x-data-grid/src/components/GridScrollArea.tsx +++ b/packages/x-data-grid/src/components/GridScrollArea.tsx @@ -14,8 +14,10 @@ import { getDataGridUtilityClass, gridClasses } from '../constants'; import { useGridApiContext } from '../hooks/utils/useGridApiContext'; import { useGridApiEventHandler } from '../hooks/utils/useGridApiEventHandler'; import { useGridSelector } from '../hooks/utils/useGridSelector'; -import { gridDimensionsSelector } from '../hooks/features/dimensions/gridDimensionsSelectors'; -import { gridDimensionsColumnsTotalWidthSelector } from '../internals/selectors/dimensionSelectors'; +import { + gridDimensionsSelector, + gridDimensionsColumnsTotalWidthSelector, +} from '../hooks/features/dimensions/gridDimensionsSelectors'; import { gridDensityFactorSelector } from '../hooks/features/density/densitySelector'; import { GridScrollParams } from '../models/params/gridScrollParams'; import { GridEventListener } from '../models/events'; diff --git a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx index 2c91ddbe23c3e..c0302bc865522 100644 --- a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx +++ b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx @@ -16,7 +16,7 @@ import { useGridSelector, } from '../hooks'; import { PinnedColumnPosition } from '../internals/constants'; -import { gridDimensionsColumnsTotalWidthSelector } from '../internals/selectors/dimensionSelectors'; +import { gridDimensionsColumnsTotalWidthSelector } from '../hooks/features/dimensions/gridDimensionsSelectors'; import { GridEventListener } from '../models'; import { DataGridProcessedProps } from '../models/props/DataGridProps'; import { getDataGridUtilityClass, gridClasses } from '../constants/gridClasses'; diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index a1c3b96c20470..e5f569a880d1c 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -5,7 +5,7 @@ import { gridHasBottomFillerSelector, gridHasScrollXSelector, gridHasScrollYSelector, -} from '../../internals/selectors/dimensionSelectors'; +} from '../../hooks/features/dimensions/gridDimensionsSelectors'; import { GridScrollArea } from '../GridScrollArea'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { useGridApiContext } from '../../hooks/utils/useGridApiContext'; diff --git a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index b9e77645abc39..9da0f7bbc3fba 100644 --- a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -15,7 +15,7 @@ import { gridHasFillerSelector, gridHeaderHeightSelector, gridVerticalScrollbarWidthSelector, -} from '../../../internals/selectors/dimensionSelectors'; +} from '../dimensions/gridDimensionsSelectors'; import { gridRenderContextColumnsSelector } from '../virtualization'; import { computeOffsetLeft } from '../virtualization/useGridVirtualScroller'; import { GridColumnGroupHeader } from '../../../components/columnHeaders/GridColumnGroupHeader'; diff --git a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts index 2365ce546492f..6f7d2d3c0b12c 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts @@ -1,3 +1,45 @@ import { GridStateCommunity } from '../../../models/gridStateCommunity'; export const gridDimensionsSelector = (state: GridStateCommunity) => state.dimensions; + +export const gridRowHeightSelector = (state: GridStateCommunity) => state.dimensions.rowHeight; + +export const gridDimensionsColumnsTotalWidthSelector = (state: GridStateCommunity) => + state.dimensions.columnsTotalWidth; + +export const gridContentHeightSelector = (state: GridStateCommunity) => + state.dimensions.contentSize.height; + +export const gridHasScrollXSelector = (state: GridStateCommunity) => state.dimensions.hasScrollX; + +export const gridHasScrollYSelector = (state: GridStateCommunity) => state.dimensions.hasScrollY; + +export const gridHasFillerSelector = (state: GridStateCommunity) => + state.dimensions.columnsTotalWidth < state.dimensions.viewportOuterSize.width; + +export const gridHeaderHeightSelector = (state: GridStateCommunity) => + state.dimensions.headerHeight; + +export const gridGroupHeaderHeightSelector = (state: GridStateCommunity) => + state.dimensions.groupHeaderHeight; + +export const gridHeaderFilterHeightSelector = (state: GridStateCommunity) => + state.dimensions.headerFilterHeight; + +export const gridVerticalScrollbarWidthSelector = (state: GridStateCommunity) => + state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; + +export const gridHorizontalScrollbarHeightSelector = (state: GridStateCommunity) => + state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; + +export const gridHasBottomFillerSelector = (state: GridStateCommunity) => { + const height = state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; + const needsLastRowBorder = + state.dimensions.viewportOuterSize.height - state.dimensions.minimumSize.height > 0; + + if (height === 0 && !needsLastRowBorder) { + return false; + } + + return true; +}; diff --git a/packages/x-data-grid/src/hooks/features/dimensions/index.ts b/packages/x-data-grid/src/hooks/features/dimensions/index.ts index bc71eeab845d4..b1d96866773a1 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/index.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/index.ts @@ -1,3 +1,3 @@ export type { GridDimensionsState } from './useGridDimensions'; -export * from './gridDimensionsSelectors'; +export { gridDimensionsSelector } from './gridDimensionsSelectors'; export type { GridDimensions, GridDimensionsApi } from './gridDimensionsApi'; diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index 70b4cf19a6359..ebd1318ea31c2 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -2,7 +2,6 @@ import * as React from 'react'; import { RefObject } from '@mui/x-internals/types'; import useLazyRef from '@mui/utils/useLazyRef'; import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils'; -import { gridRowHeightSelector } from '../../../internals/selectors/dimensionSelectors'; import { ResizeObserver } from '../../../utils/ResizeObserver'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { GridRowsMetaApi, GridRowsMetaPrivateApi } from '../../../models/api/gridRowsMetaApi'; @@ -17,7 +16,10 @@ import { gridPaginationSelector } from '../pagination/gridPaginationSelector'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; import { gridPinnedRowsSelector, gridRowCountSelector } from './gridRowsSelector'; -import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; +import { + gridDimensionsSelector, + gridRowHeightSelector, +} from '../dimensions/gridDimensionsSelectors'; import { getValidRowHeight, getRowHeightWarning } from './gridRowsUtils'; import type { HeightEntry } from './gridRowsMetaInterfaces'; diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index aa508c0306e35..24c7a36ab476e 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -10,12 +10,13 @@ import useTimeout from '@mui/utils/useTimeout'; import { useRtl } from '@mui/system/RtlProvider'; import reactMajor from '@mui/x-internals/reactMajor'; import { + gridDimensionsSelector, gridDimensionsColumnsTotalWidthSelector, gridContentHeightSelector, gridHasFillerSelector, gridRowHeightSelector, gridVerticalScrollbarWidthSelector, -} from '../../../internals/selectors/dimensionSelectors'; +} from '../dimensions/gridDimensionsSelectors'; import type { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext'; import { useGridRootProps } from '../../utils/useGridRootProps'; @@ -27,7 +28,6 @@ import { gridColumnPositionsSelector, gridHasColSpanSelector, } from '../columns/gridColumnsSelector'; -import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors'; import { gridPinnedRowsSelector } from '../rows/gridRowsSelector'; import { GridPinnedRowsPosition } from '../rows/gridRowsInterfaces'; import { useGridVisibleRows, getVisibleRows } from '../../utils/useGridVisibleRows'; diff --git a/packages/x-data-grid/src/internals/index.ts b/packages/x-data-grid/src/internals/index.ts index 14a491cc80231..96eb78a72a688 100644 --- a/packages/x-data-grid/src/internals/index.ts +++ b/packages/x-data-grid/src/internals/index.ts @@ -129,6 +129,7 @@ export { dimensionsStateInitializer, useGridDimensions, } from '../hooks/features/dimensions/useGridDimensions'; +export * from '../hooks/features/dimensions/gridDimensionsSelectors'; export { useGridStatePersistence } from '../hooks/features/statePersistence/useGridStatePersistence'; export type { GridRestoreStatePreProcessingContext } from '../hooks/features/statePersistence/gridStatePersistenceInterface'; export { @@ -181,5 +182,3 @@ export { serializeCellValue } from '../hooks/features/export/serializers/csvSeri export * from './utils'; export * from './constants'; export type { Localization } from '../utils/getGridLocalization'; - -export * from './selectors/dimensionSelectors'; diff --git a/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts b/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts deleted file mode 100644 index 9e836ee313534..0000000000000 --- a/packages/x-data-grid/src/internals/selectors/dimensionSelectors.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { GridStateCommunity } from '../../models/gridStateCommunity'; - -export const gridRowHeightSelector = (state: GridStateCommunity) => state.dimensions.rowHeight; - -export const gridDimensionsColumnsTotalWidthSelector = (state: GridStateCommunity) => - state.dimensions.columnsTotalWidth; - -export const gridContentHeightSelector = (state: GridStateCommunity) => - state.dimensions.contentSize.height; - -export const gridHasScrollXSelector = (state: GridStateCommunity) => state.dimensions.hasScrollX; - -export const gridHasScrollYSelector = (state: GridStateCommunity) => state.dimensions.hasScrollY; - -export const gridHasFillerSelector = (state: GridStateCommunity) => - state.dimensions.columnsTotalWidth < state.dimensions.viewportOuterSize.width; - -export const gridHeaderHeightSelector = (state: GridStateCommunity) => - state.dimensions.headerHeight; - -export const gridGroupHeaderHeightSelector = (state: GridStateCommunity) => - state.dimensions.groupHeaderHeight; - -export const gridHeaderFilterHeightSelector = (state: GridStateCommunity) => - state.dimensions.headerFilterHeight; - -export const gridVerticalScrollbarWidthSelector = (state: GridStateCommunity) => - state.dimensions.hasScrollY ? state.dimensions.scrollbarSize : 0; - -export const gridHorizontalScrollbarHeightSelector = (state: GridStateCommunity) => - state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; - -export const gridHasBottomFillerSelector = (state: GridStateCommunity) => { - const height = state.dimensions.hasScrollX ? state.dimensions.scrollbarSize : 0; - const needsLastRowBorder = - state.dimensions.viewportOuterSize.height - state.dimensions.minimumSize.height > 0; - - if (height === 0 && !needsLastRowBorder) { - return false; - } - - return true; -}; From 6bc48b273f1de6365360f2928866ea7c6567c371 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Wed, 5 Feb 2025 17:24:46 +0100 Subject: [PATCH 127/129] keep only one gridColumnsTotalWidthSelector --- .../columnHeaders/useGridColumnHeaders.tsx | 4 ++-- .../src/components/GridScrollArea.tsx | 4 ++-- .../components/GridSkeletonLoadingOverlay.tsx | 4 ++-- .../columnHeaders/useGridColumnHeaders.tsx | 4 ++-- .../features/columns/gridColumnsSelector.ts | 20 ---------------- .../dimensions/gridDimensionsSelectors.ts | 13 ++++++++--- .../src/hooks/features/dimensions/index.ts | 2 +- .../features/dimensions/useGridDimensions.ts | 23 ++++++++++++++++--- .../virtualization/useGridVirtualScroller.tsx | 4 ++-- 9 files changed, 41 insertions(+), 37 deletions(-) diff --git a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 8e35f73432c89..71a016ae27b5b 100644 --- a/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid-pro/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -8,7 +8,7 @@ import { GridFilterItem, } from '@mui/x-data-grid'; import { - gridDimensionsColumnsTotalWidthSelector, + gridColumnsTotalWidthSelector, gridHasFillerSelector, gridHeaderFilterHeightSelector, gridVerticalScrollbarWidthSelector, @@ -73,7 +73,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { const classes = useUtilityClasses(rootProps); const disableHeaderFiltering = !rootProps.headerFilters; const filterModel = useGridSelector(apiRef, gridFilterModelSelector); - const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); + const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector); const headerFilterHeight = useGridSelector(apiRef, gridHeaderFilterHeightSelector); const scrollbarWidth = useGridSelector(apiRef, gridVerticalScrollbarWidthSelector); diff --git a/packages/x-data-grid/src/components/GridScrollArea.tsx b/packages/x-data-grid/src/components/GridScrollArea.tsx index c4286ff8c22b2..af98a1bd0c2d3 100644 --- a/packages/x-data-grid/src/components/GridScrollArea.tsx +++ b/packages/x-data-grid/src/components/GridScrollArea.tsx @@ -16,7 +16,7 @@ import { useGridApiEventHandler } from '../hooks/utils/useGridApiEventHandler'; import { useGridSelector } from '../hooks/utils/useGridSelector'; import { gridDimensionsSelector, - gridDimensionsColumnsTotalWidthSelector, + gridColumnsTotalWidthSelector, } from '../hooks/features/dimensions/gridDimensionsSelectors'; import { gridDensityFactorSelector } from '../hooks/features/density/densitySelector'; import { GridScrollParams } from '../models/params/gridScrollParams'; @@ -100,7 +100,7 @@ function GridScrollAreaContent(props: ScrollAreaProps) { const apiRef = useGridApiContext(); const timeout = useTimeout(); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); - const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); + const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); const sideOffset = useGridSelector(apiRef, offsetSelector, scrollDirection); const getCanScrollMore = () => { diff --git a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx index c0302bc865522..db9651d1dbd95 100644 --- a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx +++ b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx @@ -16,7 +16,7 @@ import { useGridSelector, } from '../hooks'; import { PinnedColumnPosition } from '../internals/constants'; -import { gridDimensionsColumnsTotalWidthSelector } from '../hooks/features/dimensions/gridDimensionsSelectors'; +import { gridColumnsTotalWidthSelector } from '../hooks/features/dimensions/gridDimensionsSelectors'; import { GridEventListener } from '../models'; import { DataGridProcessedProps } from '../models/props/DataGridProps'; import { getDataGridUtilityClass, gridClasses } from '../constants/gridClasses'; @@ -64,7 +64,7 @@ const GridSkeletonLoadingOverlay = forwardRef positions.filter((value) => value <= totalWidth).length, diff --git a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 9da0f7bbc3fba..ff382271dd348 100644 --- a/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -10,7 +10,7 @@ import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler'; import { GridEventListener } from '../../../models/events'; import { GridColumnHeaderItem } from '../../../components/columnHeaders/GridColumnHeaderItem'; import { - gridDimensionsColumnsTotalWidthSelector, + gridColumnsTotalWidthSelector, gridGroupHeaderHeightSelector, gridHasFillerSelector, gridHeaderHeightSelector, @@ -111,7 +111,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const columnsLookup = useGridSelector(apiRef, gridColumnLookupSelector); const offsetLeft = computeOffsetLeft(columnPositions, renderContext, pinnedColumns.left.length); - const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); + const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector); const headerHeight = useGridSelector(apiRef, gridHeaderHeightSelector); const groupHeaderHeight = useGridSelector(apiRef, gridGroupHeaderHeightSelector); diff --git a/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts b/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts index f660021ad3908..7c35559f3c62b 100644 --- a/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts +++ b/packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts @@ -6,7 +6,6 @@ import { EMPTY_PINNED_COLUMN_FIELDS, } from './gridColumnsInterfaces'; import { gridIsRtlSelector } from '../../core/gridCoreSelector'; -import { roundToDecimalPlaces } from '../../../utils/roundToDecimalPlaces'; /** * Get the columns state @@ -150,25 +149,6 @@ export const gridColumnPositionsSelector = createSelectorMemoized( }, ); -/** - * Get the summed width of all the visible columns. - * @category Visible Columns - */ -export const gridColumnsTotalWidthSelector = createSelector( - gridVisibleColumnDefinitionsSelector, - gridColumnPositionsSelector, - (visibleColumns, positions) => { - const colCount = visibleColumns.length; - if (colCount === 0) { - return 0; - } - return roundToDecimalPlaces( - positions[colCount - 1] + visibleColumns[colCount - 1].computedWidth, - 1, - ); - }, -); - /** * Get the filterable columns as an array. * @category Columns diff --git a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts index 6f7d2d3c0b12c..b117c7c677595 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/gridDimensionsSelectors.ts @@ -1,11 +1,18 @@ import { GridStateCommunity } from '../../../models/gridStateCommunity'; +import { createSelector } from '../../../utils/createSelector'; export const gridDimensionsSelector = (state: GridStateCommunity) => state.dimensions; -export const gridRowHeightSelector = (state: GridStateCommunity) => state.dimensions.rowHeight; +/** + * Get the summed width of all the visible columns. + * @category Visible Columns + */ +export const gridColumnsTotalWidthSelector = createSelector( + gridDimensionsSelector, + (dimensions) => dimensions.columnsTotalWidth, +); -export const gridDimensionsColumnsTotalWidthSelector = (state: GridStateCommunity) => - state.dimensions.columnsTotalWidth; +export const gridRowHeightSelector = (state: GridStateCommunity) => state.dimensions.rowHeight; export const gridContentHeightSelector = (state: GridStateCommunity) => state.dimensions.contentSize.height; diff --git a/packages/x-data-grid/src/hooks/features/dimensions/index.ts b/packages/x-data-grid/src/hooks/features/dimensions/index.ts index b1d96866773a1..8d50106f7e8b3 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/index.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/index.ts @@ -1,3 +1,3 @@ export type { GridDimensionsState } from './useGridDimensions'; -export { gridDimensionsSelector } from './gridDimensionsSelectors'; +export { gridDimensionsSelector, gridColumnsTotalWidthSelector } from './gridDimensionsSelectors'; export type { GridDimensions, GridDimensionsApi } from './gridDimensionsApi'; diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 11ea5dda032b2..1c1c1ab3b5244 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -11,11 +11,13 @@ import { ElementSize } from '../../../models'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { useGridApiOptionHandler } from '../../utils/useGridApiEventHandler'; import { useGridApiMethod } from '../../utils/useGridApiMethod'; +import { createSelector } from '../../../utils/createSelector'; import { useGridLogger } from '../../utils/useGridLogger'; import { DataGridProcessedProps } from '../../../models/props/DataGridProps'; import { GridDimensions, GridDimensionsApi, GridDimensionsPrivateApi } from './gridDimensionsApi'; import { - gridColumnsTotalWidthSelector, + gridColumnPositionsSelector, + gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, } from '../columns'; import { gridDimensionsSelector } from './gridDimensionsSelectors'; @@ -96,13 +98,28 @@ export const dimensionsStateInitializer: GridStateInitializer = ( }; }; +export const columnsTotalWidthSelector = createSelector( + gridVisibleColumnDefinitionsSelector, + gridColumnPositionsSelector, + (visibleColumns, positions) => { + const colCount = visibleColumns.length; + if (colCount === 0) { + return 0; + } + return roundToDecimalPlaces( + positions[colCount - 1] + visibleColumns[colCount - 1].computedWidth, + 1, + ); + }, +); + export function useGridDimensions(apiRef: RefObject, props: RootProps) { const logger = useGridLogger(apiRef, 'useResizeContainer'); const errorShown = React.useRef(false); const rootDimensionsRef = React.useRef(EMPTY_SIZE); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); - const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); + const columnsTotalWidth = useGridSelector(apiRef, columnsTotalWidthSelector); const isFirstSizing = React.useRef(true); const { @@ -404,7 +421,7 @@ function getStaticDimensions( headerFilterHeight: Math.floor( (props.headerFilterHeight ?? props.columnHeaderHeight) * density, ), - columnsTotalWidth: gridColumnsTotalWidthSelector(apiRef), + columnsTotalWidth: columnsTotalWidthSelector(apiRef), headersTotalHeight: getTotalHeaderHeight(apiRef, props), leftPinnedWidth: pinnedColumnns.left.reduce((w, col) => w + col.computedWidth, 0), rightPinnedWidth: pinnedColumnns.right.reduce((w, col) => w + col.computedWidth, 0), diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index 24c7a36ab476e..b87bd89d4b9c3 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -11,7 +11,7 @@ import { useRtl } from '@mui/system/RtlProvider'; import reactMajor from '@mui/x-internals/reactMajor'; import { gridDimensionsSelector, - gridDimensionsColumnsTotalWidthSelector, + gridColumnsTotalWidthSelector, gridContentHeightSelector, gridHasFillerSelector, gridRowHeightSelector, @@ -133,7 +133,7 @@ export const useGridVirtualScroller = () => { const rowHeight = useGridSelector(apiRef, gridRowHeightSelector); const contentHeight = useGridSelector(apiRef, gridContentHeightSelector); - const columnsTotalWidth = useGridSelector(apiRef, gridDimensionsColumnsTotalWidthSelector); + const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); const needsHorizontalScrollbar = useGridSelector(apiRef, needsHorizontalScrollbarSelector); const verticalScrollbarWidth = useGridSelector(apiRef, gridVerticalScrollbarWidthSelector); const gridHasFiller = useGridSelector(apiRef, gridHasFillerSelector); From 3771d7ac6dc50f9d2274a4d6f2ce4ffeaee8b035 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Wed, 5 Feb 2025 17:33:17 +0100 Subject: [PATCH 128/129] remove export --- .../src/hooks/features/dimensions/useGridDimensions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 1c1c1ab3b5244..1843b7bfb1325 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -98,7 +98,7 @@ export const dimensionsStateInitializer: GridStateInitializer = ( }; }; -export const columnsTotalWidthSelector = createSelector( +const columnsTotalWidthSelector = createSelector( gridVisibleColumnDefinitionsSelector, gridColumnPositionsSelector, (visibleColumns, positions) => { From fa21f18a01a5cb831ee6b2bfe9a2734dbc673f70 Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskyi Date: Wed, 5 Feb 2025 17:39:32 +0100 Subject: [PATCH 129/129] format markfown diff --- .../migration-data-grid-v7/migration-data-grid-v7.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md index 5ba9f9de3cb23..bd7e499f4701a 100644 --- a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md +++ b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md @@ -119,8 +119,8 @@ Below are described the steps you need to make to migrate from v7 to v8. - The `visibleRowsLookup` state does not contain `true` values anymore. If the row is not visible, the value is `false`. Otherwise, the row id is not present in the object: ```diff const visibleRowsLookup = gridVisibleRowsLookupSelector(apiRef); - -const isRowVisible = visibleRowsLookup[rowId] === true; - +const isRowVisible = visibleRowsLookup[rowId] !== false; + -const isRowVisible = visibleRowsLookup[rowId] === true; + +const isRowVisible = visibleRowsLookup[rowId] !== false; ``` ### Other exports