diff --git a/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.test.tsx b/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.test.tsx
index 99bb3ffdd4..7092a19688 100644
--- a/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.test.tsx
+++ b/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.test.tsx
@@ -537,4 +537,88 @@ describe('VirtualTableLayout', () => {
});
});
});
+
+ describe('row heights', () => {
+ const getBoundingClientRect = () => ({
+ height: 70,
+ });
+
+ const newProps = {
+ ...defaultProps,
+ tableComponent: ({ forwardedRef, ...props }) => {
+ (forwardedRef as any).current = { getBoundingClientRect };
+ return
;
+ },
+ rowComponent: ({ forwardedRef }) => {
+ (forwardedRef as any)({ getBoundingClientRect });
+ return null;
+ },
+ };
+
+ it('should specify correct row height at startup', () => {
+ expect.hasAssertions();
+
+ const rows = [
+ { key: 1 },
+ { key: 2, height: 10 },
+ ];
+
+ getCollapsedGrids
+ .mockImplementationOnce((args) => {
+ const { getRowHeight } = args;
+ expect(getRowHeight(rows[0]))
+ .toEqual(newProps.estimatedRowHeight);
+ expect(getRowHeight(rows[1]))
+ .toEqual(10);
+
+ return jest.requireActual('@devexpress/dx-grid-core').getCollapsedGrids(args);
+ });
+
+ mount((
+
+ ));
+ });
+
+ it('should store row height when rendered', () => {
+ const rows = [
+ { key: 1 },
+ { key: 2, height: 10 },
+ ];
+
+ mount((
+
+ ));
+
+ const { getRowHeight } = getCollapsedGrids.mock.calls[0][0];
+ expect(getRowHeight(rows[0]))
+ .toEqual(70);
+ expect(getRowHeight(rows[1]))
+ .toEqual(70);
+ });
+
+ it('should clear row height when rows updated', () => {
+ const rows = [
+ { key: 11 },
+ { key: 12 },
+ ];
+
+ const tree = mount((
+
+ ));
+ tree.setProps({ bodyRows: [rows[0]] });
+
+ const { getRowHeight } = getCollapsedGrids.mock.calls[0][0];
+ expect(getRowHeight(rows[1]))
+ .toEqual(newProps.estimatedRowHeight);
+ });
+ });
});
diff --git a/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.tsx b/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.tsx
index 06b5261581..10f52b4f43 100644
--- a/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.tsx
+++ b/packages/dx-react-grid/src/components/table-layout/virtual-table-layout.tsx
@@ -35,6 +35,7 @@ export class VirtualTableLayout extends React.PureComponent(),
viewportTop: 0,
skipItems: [0, 0],
containerHeight: 600,
@@ -63,13 +64,19 @@ export class VirtualTableLayout extends React.PureComponent {
+ const rowHeight = prevRowHeight.get(row.key);
+ if (rowHeight !== undefined) {
+ acc.set(row.key, rowHeight);
+ }
+ return acc;
+ },
+ new Map(),
+ );
+ return { rowHeights };
+ }
+
getRowHeight = (row) => {
+ const { rowHeights } = this.state;
+ const { estimatedRowHeight } = this.props;
if (row) {
- const realHeight = this.rowRefs.get(row.key)?.getBoundingClientRect().height;
- return row.height || realHeight || this.props.estimatedRowHeight;
+ const storedHeight = rowHeights.get(row.key);
+ if (storedHeight !== undefined) return storedHeight;
+ if (row.height) return row.height;
+ }
+ return estimatedRowHeight;
+ }
+
+ storeRowHeights() {
+ const rowsWithChangedHeights = Array.from(this.rowRefs.entries())
+ .map(([row, ref]) => [row, ref])
+ .filter(([, node]) => !!node)
+ .map(([row, node]) => [row, node.getBoundingClientRect().height])
+ .filter(([row, height]) => row.type !== TABLE_STUB_TYPE && height !== this.getRowHeight(row));
+
+ if (rowsWithChangedHeights.length) {
+ const { rowHeights } = this.state;
+ rowsWithChangedHeights
+ .forEach(([row, height]) => rowHeights.set(row.key, height));
+
+ this.setState({
+ rowHeights,
+ });
}
- return this.props.estimatedRowHeight;
}
onScroll = (e) => {
diff --git a/packages/dx-react-grid/src/types/layout/table-layout.types.ts b/packages/dx-react-grid/src/types/layout/table-layout.types.ts
index 58ced17d95..bbe7f87230 100644
--- a/packages/dx-react-grid/src/types/layout/table-layout.types.ts
+++ b/packages/dx-react-grid/src/types/layout/table-layout.types.ts
@@ -53,6 +53,7 @@ export interface VirtualTableLayoutProps extends TableLayoutProps {
}
/** @internal */
export type VirtualTableLayoutState = {
+ rowHeights: Map,
viewportTop: number,
skipItems: [number, number],
containerHeight: number,