Skip to content

Commit

Permalink
fix memo (grid header, cells, rows)
Browse files Browse the repository at this point in the history
fix memo (grid header, cells, rows)

fix tests

fix row re-rendering on cell focus change

fix gridheaders re-rendering on each focus change

move grid headers, body and footer to GridRoot, and memoize GridRoot

fix VirtualScroller re-rendering on each focus change

fix virtualRow in pinned rows

fix focusedVirtualCell potentially depending on stale rendercontext

undo some testing changes

docs:api

whoopsie

fix pinned skeleton overlays

move PinnedPosition enum to internals

rename to PinnedColumnPosition

rebuild docs api

Update packages/x-data-grid/src/components/containers/GridRoot.tsx

Co-authored-by: Rom Grk <[email protected]>
Signed-off-by: Lauri <[email protected]>

fastmemo

undo erroneous change

gridheaderfilter styles change

reduce lookup cost

alternative lookup with maps

fix useGridVisibleRows memoization

don't filter rows is there's no depth

fix filter selector

make it nicer

test with row lookupMap

unit tests passing + clean up a bit

docs:api

attachPinnedStyle

lint

fix up virtual focus cell selector

pass only necessary dimensions into the GridRow

rebase and refactor #15929

proptypes

fix double-rendering of pinned columns introduced by #15116

fix tests

re-evaluate renderContext on toggling virtualization to avoid manual overrides to renderContext

fix tests

lint
  • Loading branch information
lauri865 committed Jan 14, 2025
1 parent 55b01ba commit 0d0d88c
Show file tree
Hide file tree
Showing 41 changed files with 600 additions and 507 deletions.
7 changes: 7 additions & 0 deletions docs/pages/x/api/data-grid/selectors.json
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,13 @@
"description": "Get the visible pinned columns.",
"supportsApiRef": true
},
{
"name": "gridVisibleRowsSelector",
"returnType": "{ rows: GridRowEntry<GridValidRowModel>[]; range: { firstRowIndex: number; lastRowIndex: number } | null; rowToIndexMap: Map<GridValidRowModel, number> }",
"category": "Pagination",
"description": "Get the rows, range and rowIndex lookup map after filtering and sorting.\nDoes not contain the collapsed children.",
"supportsApiRef": true
},
{
"name": "selectedGridRowsCountSelector",
"returnType": "number",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { useLicenseVerifier, Watermark } from '@mui/x-license';
import {
GridBody,
GridFooterPlaceholder,
GridHeader,
GridRoot,
GridContextProvider,
GridValidRowModel,
} from '@mui/x-data-grid-pro';
import { GridRoot, GridContextProvider, GridValidRowModel } from '@mui/x-data-grid-pro';
import {
propValidatorsDataGrid,
propValidatorsDataGridPro,
Expand Down Expand Up @@ -63,11 +56,7 @@ const DataGridPremiumRaw = forwardRef(function DataGridPremium<R extends GridVal
{...props.slotProps?.root}
ref={ref}
>
<GridHeader />
<GridBody>
<Watermark packageName="x-data-grid-premium" releaseInfo={releaseInfo} />
</GridBody>
<GridFooterPlaceholder />
<Watermark packageName="x-data-grid-premium" releaseInfo={releaseInfo} />
</GridRoot>
</GridContextProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export const useDataGridPremiumComponent = (
useGridInitializeState(columnPinningStateInitializer, apiRef, props);
useGridInitializeState(columnsStateInitializer, apiRef, props);
useGridInitializeState(rowPinningStateInitializer, apiRef, props);
useGridInitializeState(paginationStateInitializer, apiRef, props);
useGridInitializeState(rowsStateInitializer, apiRef, props);
useGridInitializeState(editingStateInitializer, apiRef, props);
useGridInitializeState(focusStateInitializer, apiRef, props);
Expand All @@ -142,7 +143,6 @@ export const useDataGridPremiumComponent = (
useGridInitializeState(densityStateInitializer, apiRef, props);
useGridInitializeState(columnReorderStateInitializer, apiRef, props);
useGridInitializeState(columnResizeStateInitializer, apiRef, props);
useGridInitializeState(paginationStateInitializer, apiRef, props);
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(columnMenuStateInitializer, apiRef, props);
useGridInitializeState(columnGroupsStateInitializer, apiRef, props);
Expand Down
15 changes: 2 additions & 13 deletions packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { useLicenseVerifier, Watermark } from '@mui/x-license';
import {
GridBody,
GridFooterPlaceholder,
GridHeader,
GridRoot,
GridContextProvider,
GridValidRowModel,
} from '@mui/x-data-grid';
import { GridRoot, GridContextProvider, GridValidRowModel } from '@mui/x-data-grid';
import { validateProps } from '@mui/x-data-grid/internals';
import { forwardRef } from '@mui/x-internals/forwardRef';
import { useDataGridProComponent } from './useDataGridProComponent';
Expand Down Expand Up @@ -50,11 +43,7 @@ const DataGridProRaw = forwardRef(function DataGridPro<R extends GridValidRowMod
{...props.slotProps?.root}
ref={ref}
>
<GridHeader />
<GridBody>
<Watermark packageName="x-data-grid-pro" releaseInfo={releaseInfo} />
</GridBody>
<GridFooterPlaceholder />
<Watermark packageName="x-data-grid-pro" releaseInfo={releaseInfo} />
</GridRoot>
</GridContextProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export const useDataGridProComponent = (
useGridInitializeState(columnPinningStateInitializer, apiRef, props);
useGridInitializeState(columnsStateInitializer, apiRef, props);
useGridInitializeState(rowPinningStateInitializer, apiRef, props);
useGridInitializeState(paginationStateInitializer, apiRef, props);
useGridInitializeState(rowsStateInitializer, apiRef, props);
useGridInitializeState(editingStateInitializer, apiRef, props);
useGridInitializeState(focusStateInitializer, apiRef, props);
Expand All @@ -127,7 +128,6 @@ export const useDataGridProComponent = (
useGridInitializeState(densityStateInitializer, apiRef, props);
useGridInitializeState(columnReorderStateInitializer, apiRef, props);
useGridInitializeState(columnResizeStateInitializer, apiRef, props);
useGridInitializeState(paginationStateInitializer, apiRef, props);
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(columnMenuStateInitializer, apiRef, props);
useGridInitializeState(columnGroupsStateInitializer, apiRef, props);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ import {
GridFilterInputSingleSelect,
gridFilterModelSelector,
gridFilterableColumnLookupSelector,
GridPinnedColumnPosition,
} from '@mui/x-data-grid';
import {
PinnedColumnPosition,
GridStateColDef,
useGridPrivateApiContext,
gridHeaderFilteringEditFieldSelector,
gridHeaderFilteringMenuSelector,
isNavigationKey,
shouldCellShowLeftBorder,
shouldCellShowRightBorder,
rtlFlipSide,
attachPinnedStyle,
} from '@mui/x-data-grid/internals';
import { useRtl } from '@mui/system/RtlProvider';
import { forwardRef } from '@mui/x-internals/forwardRef';
import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
import { DataGridProProcessedProps } from '../../models/dataGridProProps';
Expand All @@ -55,16 +56,16 @@ export interface GridHeaderFilterCellProps extends Pick<GridStateColDef, 'header
item: GridFilterItem;
showClearIcon?: boolean;
InputComponentProps: GridFilterOperator['InputComponentProps'];
pinnedPosition?: GridPinnedColumnPosition;
pinnedPosition?: PinnedColumnPosition;
pinnedOffset?: number;
style?: React.CSSProperties;
indexInSection: number;
sectionLength: number;
gridHasFiller: boolean;
showLeftBorder: boolean;
showRightBorder: boolean;
}

type OwnerState = DataGridProProcessedProps & {
colDef: GridColDef;
pinnedPosition?: GridPinnedColumnPosition;
pinnedPosition?: PinnedColumnPosition;
showRightBorder: boolean;
showLeftBorder: boolean;
};
Expand All @@ -81,8 +82,8 @@ const useUtilityClasses = (ownerState: OwnerState) => {
'withBorderColor',
showRightBorder && 'columnHeader--withRightBorder',
showLeftBorder && 'columnHeader--withLeftBorder',
pinnedPosition === 'left' && 'columnHeader--pinnedLeft',
pinnedPosition === 'right' && 'columnHeader--pinnedRight',
pinnedPosition === PinnedColumnPosition.LEFT && 'columnHeader--pinnedLeft',
pinnedPosition === PinnedColumnPosition.RIGHT && 'columnHeader--pinnedRight',
],
};

Expand Down Expand Up @@ -115,14 +116,15 @@ const GridHeaderFilterCell = forwardRef<HTMLDivElement, GridHeaderFilterCellProp
InputComponentProps,
showClearIcon = true,
pinnedPosition,
pinnedOffset,
style: styleProp,
indexInSection,
sectionLength,
gridHasFiller,
showLeftBorder,
showRightBorder,
...other
} = props;

const apiRef = useGridPrivateApiContext();
const isRtl = useRtl();
const columnFields = useGridSelector(apiRef, gridVisibleColumnFieldsSelector);
const rootProps = useGridRootProps();
const cellRef = React.useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -282,15 +284,6 @@ const GridHeaderFilterCell = forwardRef<HTMLDivElement, GridHeaderFilterCellProp
[onMouseDown, onKeyDown, publish],
);

const showLeftBorder = shouldCellShowLeftBorder(pinnedPosition, indexInSection);
const showRightBorder = shouldCellShowRightBorder(
pinnedPosition,
indexInSection,
sectionLength,
rootProps.showCellVerticalBorder,
gridHasFiller,
);

const ownerState: OwnerState = {
...rootProps,
pinnedPosition,
Expand All @@ -313,14 +306,19 @@ const GridHeaderFilterCell = forwardRef<HTMLDivElement, GridHeaderFilterCellProp

const isFilterActive = isApplied || hasFocus;

const style = {
height,
width,
...styleProp,
};

const pinnedSide = rtlFlipSide(pinnedPosition, isRtl);
attachPinnedStyle(style, pinnedSide, pinnedOffset);

return (
<div
className={clsx(classes.root, headerClassName)}
style={{
height,
width,
...styleProp,
}}
style={style}
role="columnheader"
aria-colindex={colIndex + 1}
aria-label={headerFilterComponent == null ? (colDef.headerName ?? colDef.field) : undefined}
Expand Down Expand Up @@ -397,7 +395,6 @@ GridHeaderFilterCell.propTypes = {
// ----------------------------------------------------------------------
colDef: PropTypes.object.isRequired,
colIndex: PropTypes.number.isRequired,
gridHasFiller: PropTypes.bool.isRequired,
hasFocus: PropTypes.bool,
/**
* Class name added to the column header cell.
Expand All @@ -407,17 +404,18 @@ GridHeaderFilterCell.propTypes = {
current: PropTypes.object,
}).isRequired,
height: PropTypes.number.isRequired,
indexInSection: PropTypes.number.isRequired,
InputComponentProps: PropTypes.object,
item: PropTypes.shape({
field: PropTypes.string.isRequired,
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
operator: PropTypes.string.isRequired,
value: PropTypes.any,
}).isRequired,
pinnedPosition: PropTypes.oneOf(['left', 'right']),
sectionLength: PropTypes.number.isRequired,
pinnedOffset: PropTypes.number,
pinnedPosition: PropTypes.oneOf([0, 1, 2, 3]),
showClearIcon: PropTypes.bool,
showLeftBorder: PropTypes.bool.isRequired,
showRightBorder: PropTypes.bool.isRequired,
sortIndex: PropTypes.number,
style: PropTypes.object,
tabIndex: PropTypes.oneOf([-1, 0]).isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
gridTabIndexColumnHeaderFilterSelector,
getDataGridUtilityClass,
GridFilterItem,
GridPinnedColumnPosition,
gridDimensionsSelector,
} from '@mui/x-data-grid';
import {
Expand All @@ -17,6 +16,9 @@ import {
getGridFilter,
GridStateColDef,
GridColumnHeaderRow,
shouldCellShowLeftBorder,
shouldCellShowRightBorder,
PinnedColumnPosition,
} from '@mui/x-data-grid/internals';
import composeClasses from '@mui/utils/composeClasses';
import { useGridRootProps } from '../../utils/useGridRootProps';
Expand Down Expand Up @@ -46,12 +48,13 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
);
const {
getColumnsToRender,
getPinnedCellOffset,
renderContext,
leftRenderContext,
rightRenderContext,
pinnedColumns,
visibleColumns,
getCellOffsetStyle,
columnPositions,
...otherProps
} = useGridColumnHeadersCommunity({
...props,
Expand Down Expand Up @@ -117,11 +120,27 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
const item = getFilterItem(colDef);

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

const indexInSection = i;
const sectionLength = renderedColumns.length;

const showLeftBorder = shouldCellShowLeftBorder(pinnedPosition, indexInSection);
const showRightBorder = shouldCellShowRightBorder(
pinnedPosition,
indexInSection,
sectionLength,
rootProps.showCellVerticalBorder,
gridHasFiller,
);

filters.push(
<rootProps.slots.headerFilterCell
Expand All @@ -137,10 +156,9 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
data-field={colDef.field}
item={item}
pinnedPosition={pinnedPosition}
style={style}
indexInSection={i}
sectionLength={renderedColumns.length}
gridHasFiller={gridHasFiller}
pinnedOffset={pinnedOffset}
showLeftBorder={showLeftBorder}
showRightBorder={showRightBorder}
{...rootProps.slotProps?.headerFilterCell}
/>,
);
Expand All @@ -164,7 +182,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
>
{leftRenderContext &&
getColumnFilters({
position: GridPinnedColumnPosition.LEFT,
position: PinnedColumnPosition.LEFT,
renderContext: leftRenderContext,
maxLastColumn: leftRenderContext.lastColumnIndex,
})}
Expand All @@ -174,7 +192,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
})}
{rightRenderContext &&
getColumnFilters({
position: GridPinnedColumnPosition.RIGHT,
position: PinnedColumnPosition.RIGHT,
renderContext: rightRenderContext,
maxLastColumn: rightRenderContext.lastColumnIndex,
})}
Expand Down
8 changes: 2 additions & 6 deletions packages/x-data-grid/src/DataGrid/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { forwardRef } from '@mui/x-internals/forwardRef';
import { GridBody, GridFooterPlaceholder, GridHeader, GridRoot } from '../components';
import { GridRoot } from '../components';
import { useGridAriaAttributes } from '../hooks/utils/useGridAriaAttributes';
import { useGridRowAriaAttributes } from '../hooks/features/rows/useGridRowAriaAttributes';
import { DataGridProcessedProps, DataGridProps } from '../models/props/DataGridProps';
Expand Down Expand Up @@ -61,11 +61,7 @@ const DataGridRaw = forwardRef(function DataGrid<R extends GridValidRowModel>(
sx={props.sx}
{...props.slotProps?.root}
ref={ref}
>
<GridHeader />
<GridBody />
<GridFooterPlaceholder />
</GridRoot>
/>
</GridContextProvider>
);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/x-data-grid/src/DataGrid/useDataGridComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export const useDataGridComponent = (
useGridInitializeState(dimensionsStateInitializer, apiRef, props);
useGridInitializeState(rowSelectionStateInitializer, apiRef, props);
useGridInitializeState(columnsStateInitializer, apiRef, props);
useGridInitializeState(paginationStateInitializer, apiRef, props);
useGridInitializeState(rowsStateInitializer, apiRef, props);
useGridInitializeState(editingStateInitializer, apiRef, props);
useGridInitializeState(focusStateInitializer, apiRef, props);
Expand All @@ -92,7 +93,6 @@ export const useDataGridComponent = (
useGridInitializeState(rowSpanningStateInitializer, apiRef, props);
useGridInitializeState(densityStateInitializer, apiRef, props);
useGridInitializeState(columnResizeStateInitializer, apiRef, props);
useGridInitializeState(paginationStateInitializer, apiRef, props);
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(columnMenuStateInitializer, apiRef, props);
useGridInitializeState(columnGroupsStateInitializer, apiRef, props);
Expand Down
Loading

0 comments on commit 0d0d88c

Please sign in to comment.