From 18cd8e182b74a2cfa5889c7b9fba8d7d5016441d Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 21 Apr 2021 15:21:29 +0200 Subject: [PATCH] [DataGrid] Fix reset of virtualPage (#1451) --- .../containers/GridDataContainer.tsx | 15 ++++--- .../virtualization/useGridVirtualRows.ts | 5 +++ .../hooks/root/gridContainerSizesSelector.ts | 8 ++++ .../grid/x-grid/src/tests/rows.XGrid.test.tsx | 28 +++++++++++++ .../src/stories/grid-rows.stories.tsx | 41 ++++++++++++++++++- 5 files changed, 91 insertions(+), 6 deletions(-) diff --git a/packages/grid/_modules_/grid/components/containers/GridDataContainer.tsx b/packages/grid/_modules_/grid/components/containers/GridDataContainer.tsx index 5148c341332a..be47e09a62a1 100644 --- a/packages/grid/_modules_/grid/components/containers/GridDataContainer.tsx +++ b/packages/grid/_modules_/grid/components/containers/GridDataContainer.tsx @@ -1,6 +1,10 @@ import * as React from 'react'; import { GRID_DATA_CONTAINER_CSS_CLASS } from '../../constants/cssClassesConstants'; -import { useGridState } from '../../hooks/features/core/useGridState'; +import { useGridSelector } from '../../hooks/features/core/useGridSelector'; +import { + gridDataContainerSizesSelector, + gridScrollBarSizeSelector, +} from '../../hooks/root/gridContainerSizesSelector'; import { classnames } from '../../utils'; import { GridApiContext } from '../GridApiContext'; @@ -9,14 +13,15 @@ type GridDataContainerProps = React.HTMLAttributes; export function GridDataContainer(props: GridDataContainerProps) { const { className, ...other } = props; const apiRef = React.useContext(GridApiContext); - const [gridState] = useGridState(apiRef!); + const dataContainerSizes = useGridSelector(apiRef!, gridDataContainerSizesSelector); + const scrollBar = useGridSelector(apiRef!, gridScrollBarSizeSelector); const style: any = { - minWidth: gridState.containerSizes?.dataContainerSizes?.width, + minWidth: dataContainerSizes?.width, }; - if (gridState.scrollBar.hasScrollY) { - style.minHeight = gridState.containerSizes?.dataContainerSizes?.height!; + if (scrollBar.hasScrollY) { + style.minHeight = dataContainerSizes?.height!; } return ( diff --git a/packages/grid/_modules_/grid/hooks/features/virtualization/useGridVirtualRows.ts b/packages/grid/_modules_/grid/hooks/features/virtualization/useGridVirtualRows.ts index 255d5ba7c1f3..286a4eb49b21 100644 --- a/packages/grid/_modules_/grid/hooks/features/virtualization/useGridVirtualRows.ts +++ b/packages/grid/_modules_/grid/hooks/features/virtualization/useGridVirtualRows.ts @@ -156,6 +156,11 @@ export const useGridVirtualRows = ( logger.debug(`Changing page from ${page} to ${nextPage}`); requireRerender = true; } else { + if (!containerProps.isVirtualized && page > 0) { + logger.debug(`Virtualization disabled, setting virtualPage to 0`); + setRenderingState({ virtualPage: 0 }); + } + scrollTo(scrollParams); } setRenderingState({ diff --git a/packages/grid/_modules_/grid/hooks/root/gridContainerSizesSelector.ts b/packages/grid/_modules_/grid/hooks/root/gridContainerSizesSelector.ts index be95358a8bd8..d090d896fcad 100644 --- a/packages/grid/_modules_/grid/hooks/root/gridContainerSizesSelector.ts +++ b/packages/grid/_modules_/grid/hooks/root/gridContainerSizesSelector.ts @@ -1,4 +1,5 @@ import { createSelector } from 'reselect'; +import { ElementSize } from '../../models/elementSize'; import { GridContainerProps } from '../../models/gridContainerProps'; import { GridState } from '../features/core/gridState'; @@ -6,6 +7,13 @@ export const gridContainerSizesSelector = (state: GridState) => state.containerS export const gridViewportSizesSelector = (state: GridState) => state.viewportSizes; export const gridScrollBarSizeSelector = (state: GridState) => state.scrollBar; +export const gridDataContainerSizesSelector = createSelector< + GridState, + GridContainerProps | null, + ElementSize | null +>(gridContainerSizesSelector, (containerSizes) => + containerSizes == null ? null : containerSizes.dataContainerSizes, +); export const gridDataContainerHeightSelector = createSelector< GridState, GridContainerProps | null, diff --git a/packages/grid/x-grid/src/tests/rows.XGrid.test.tsx b/packages/grid/x-grid/src/tests/rows.XGrid.test.tsx index 46fbe23cf1f2..f4cc5ca71e87 100644 --- a/packages/grid/x-grid/src/tests/rows.XGrid.test.tsx +++ b/packages/grid/x-grid/src/tests/rows.XGrid.test.tsx @@ -358,6 +358,34 @@ describe(' - Rows', () => { expect(isVirtualized).to.equal(false); }); + it('should set the virtual page to 0 when resetting rows to a non virtualized length', () => { + const { setProps } = render(); + + const gridWindow = document.querySelector('.MuiDataGrid-window')!; + gridWindow.scrollTop = 10e6; // scroll to the bottom + gridWindow.dispatchEvent(new Event('scroll')); + + let lastCell = document.querySelector('[role="row"]:last-child [role="cell"]:first-child')!; + expect(lastCell).to.have.text('995'); + + let virtualPage = apiRef!.current!.getState().rendering!.virtualPage; + expect(virtualPage).to.equal(98); + + setProps({ nbRows: 9 }); + + lastCell = document.querySelector('[role="row"]:last-child [role="cell"]:first-child')!; + expect(lastCell).to.have.text('8'); + + const renderingZone = document.querySelector('.MuiDataGrid-renderingZone')! as HTMLElement; + expect(renderingZone.children.length).to.equal(9); + + virtualPage = apiRef!.current!.getState().rendering!.virtualPage; + expect(virtualPage).to.equal(0); + + const isVirtualized = apiRef!.current!.getState().containerSizes!.isVirtualized; + expect(isVirtualized).to.equal(false); + }); + describe('Pagination', () => { it('should render only the pageSize', () => { render(); diff --git a/packages/storybook/src/stories/grid-rows.stories.tsx b/packages/storybook/src/stories/grid-rows.stories.tsx index 4cd64bf1476e..27ee55b9d085 100644 --- a/packages/storybook/src/stories/grid-rows.stories.tsx +++ b/packages/storybook/src/stories/grid-rows.stories.tsx @@ -1,5 +1,5 @@ -import Alert from '@material-ui/lab/Alert'; import * as React from 'react'; +import Alert from '@material-ui/lab/Alert'; import Typography from '@material-ui/core/Typography'; import Button from '@material-ui/core/Button'; import Popper from '@material-ui/core/Popper'; @@ -875,3 +875,42 @@ export function EditCellWithMessageGrid() { ); } + +export function SwitchVirtualization() { + const { data, setRowLength } = useDemoData({ + dataSet: 'Commodity', + rowLength: 200, + maxColumns: 20, + }); + + const handleButtonClick = (nbRows: number) => { + setRowLength(nbRows); + }; + + React.useLayoutEffect(() => { + const window = document.querySelector('.MuiDataGrid-window'); + if (window) { + window!.scrollTo(0, 5000); + } + }); + + return ( +
+
+ + +
+
+ +
+
+ ); +}