Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance tweaking for DataGrid #2638

Merged
merged 4 commits into from
Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 26 additions & 20 deletions src/components/datagrid/data_grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
EuiDataGridPopoverContents,
EuiDataGridColumnVisibility,
EuiDataGridToolBarVisibilityOptions,
EuiDataGridFocusedCell,
} from './data_grid_types';
import { EuiDataGridCellProps } from './data_grid_cell';
// @ts-ignore-next-line
Expand Down Expand Up @@ -287,9 +288,9 @@ function useInMemoryValues(
function createKeyDownHandler(
props: EuiDataGridProps,
visibleColumns: EuiDataGridProps['columns'],
focusedCell: [number, number],
focusedCell: EuiDataGridFocusedCell,
headerIsInteractive: boolean,
setFocusedCell: (focusedCell: [number, number]) => void,
setFocusedCell: (focusedCell: EuiDataGridFocusedCell) => void,
updateFocus: Function
) {
return (event: KeyboardEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -397,7 +398,9 @@ function useAfterRender(fn: Function): Function {
export const EuiDataGrid: FunctionComponent<EuiDataGridProps> = props => {
const [isFullScreen, setIsFullScreen] = useState(false);
const [hasRoomForGridControls, setHasRoomForGridControls] = useState(true);
const [focusedCell, setFocusedCell] = useState<[number, number] | null>(null);
const [focusedCell, setFocusedCell] = useState<EuiDataGridFocusedCell | null>(
null
);
const [containerRef, setContainerRef] = useState<HTMLDivElement | null>(null);
const [interactiveCellId] = useState(htmlIdGenerator()());

Expand Down Expand Up @@ -626,7 +629,7 @@ export const EuiDataGrid: FunctionComponent<EuiDataGridProps> = props => {
delete rest['aria-labelledby'];
}

const realizedFocusedCell: [number, number] =
const realizedFocusedCell: EuiDataGridFocusedCell =
focusedCell || (headerIsInteractive ? [0, -1] : [0, 0]);

const fullScreenSelector = (
Expand Down Expand Up @@ -664,27 +667,30 @@ export const EuiDataGrid: FunctionComponent<EuiDataGridProps> = props => {
}
});

const datagridContext = {
onFocusUpdate: (cell: [number, number], updateFocus: Function) => {
if (pagination) {
const key = `${cell[0]}-${cell[1]}`;

setCellsUpdateFocus(cellsUpdateFocus => {
const nextCellsUpdateFocus = new Map(cellsUpdateFocus);
nextCellsUpdateFocus.set(key, updateFocus);
return nextCellsUpdateFocus;
});
const datagridContext = useMemo(
() => ({
onFocusUpdate: (cell: EuiDataGridFocusedCell, updateFocus: Function) => {
if (pagination) {
const key = `${cell[0]}-${cell[1]}`;

return () => {
setCellsUpdateFocus(cellsUpdateFocus => {
const nextCellsUpdateFocus = new Map(cellsUpdateFocus);
nextCellsUpdateFocus.delete(key);
nextCellsUpdateFocus.set(key, updateFocus);
return nextCellsUpdateFocus;
});
};
}
},
};

return () => {
setCellsUpdateFocus(cellsUpdateFocus => {
const nextCellsUpdateFocus = new Map(cellsUpdateFocus);
nextCellsUpdateFocus.delete(key);
return nextCellsUpdateFocus;
});
};
}
},
}),
[pagination]
);

return (
<DataGridContext.Provider value={datagridContext}>
Expand Down
43 changes: 21 additions & 22 deletions src/components/datagrid/data_grid_body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
EuiDataGridInMemoryValues,
EuiDataGridPaginationProps,
EuiDataGridSorting,
EuiDataGridFocusedCell,
} from './data_grid_types';
import { EuiDataGridCellProps } from './data_grid_cell';
import {
Expand All @@ -27,7 +28,7 @@ interface EuiDataGridBodyProps {
schema: EuiDataGridSchema;
schemaDetectors: EuiDataGridSchemaDetector[];
popoverContents?: EuiDataGridPopoverContents;
focusedCell: EuiDataGridDataRowProps['focusedCell'];
focusedCell: EuiDataGridFocusedCell;
onCellFocus: EuiDataGridDataRowProps['onCellFocus'];
rowCount: number;
renderCellValue: EuiDataGridCellProps['renderCellValue'];
Expand Down Expand Up @@ -158,49 +159,47 @@ export const EuiDataGridBody: FunctionComponent<
return rowMap;
}, [sorting, inMemory, inMemoryValues, schema, schemaDetectors]);

const rows = useMemo(() => {
const rows = [];
for (let i = 0; i < visibleRowIndices.length; i++) {
let rowIndex = visibleRowIndices[i];
if (rowMap.hasOwnProperty(rowIndex)) {
rowIndex = rowMap[rowIndex];
}
const mergedPopoverContents = useMemo(
() => ({
...providedPopoverContents,
...popoverContents,
}),
[popoverContents]
);

const mergedPopoverContents = {
...providedPopoverContents,
...popoverContents,
};

rows.push(
const rows = useMemo(() => {
return visibleRowIndices.map((rowIndex, i) => {
rowIndex = rowMap.hasOwnProperty(rowIndex) ? rowMap[rowIndex] : rowIndex;
return (
<EuiDataGridDataRow
key={rowIndex}
columns={columns}
schema={schema}
popoverContents={mergedPopoverContents}
columnWidths={columnWidths}
defaultColumnWidth={defaultColumnWidth}
focusedCell={focusedCell}
focusedCellPositionInTheRow={
i === focusedCell[1] ? focusedCell[0] : null
}
onCellFocus={onCellFocus}
renderCellValue={renderCellValue}
rowIndex={rowIndex}
visibleRowIndex={i}
interactiveCellId={interactiveCellId}
/>
);
}

return rows;
});
}, [
visibleRowIndices,
rowMap,
columns,
schema,
mergedPopoverContents,
columnWidths,
defaultColumnWidth,
focusedCell,
onCellFocus,
renderCellValue,
rowMap,
schema,
popoverContents,
visibleRowIndices,
interactiveCellId,
]);

Expand Down
3 changes: 2 additions & 1 deletion src/components/datagrid/data_grid_context.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { EuiDataGridFocusedCell } from './data_grid_types';

export const DataGridContext = React.createContext({
onFocusUpdate: (_cell: [number, number], _updateFocus: Function) => {},
onFocusUpdate: (_cell: EuiDataGridFocusedCell, _updateFocus: Function) => {},
});
115 changes: 58 additions & 57 deletions src/components/datagrid/data_grid_data_row.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FunctionComponent, HTMLAttributes } from 'react';
import React, { FunctionComponent, HTMLAttributes, memo } from 'react';
import classnames from 'classnames';
import {
EuiDataGridColumn,
Expand All @@ -20,7 +20,7 @@ export type EuiDataGridDataRowProps = CommonProps &
popoverContents: EuiDataGridPopoverContents;
columnWidths: EuiDataGridColumnWidths;
defaultColumnWidth?: number | null;
focusedCell: [number, number];
focusedCellPositionInTheRow?: number | null;
renderCellValue: EuiDataGridCellProps['renderCellValue'];
onCellFocus: Function;
interactiveCellId: EuiDataGridCellProps['interactiveCellId'];
Expand All @@ -31,65 +31,66 @@ const DefaultColumnFormatter: EuiDataGridPopoverContent = ({ children }) => {
return <EuiText>{children}</EuiText>;
};

const EuiDataGridDataRow: FunctionComponent<
EuiDataGridDataRowProps
> = props => {
const {
columns,
schema,
popoverContents,
columnWidths,
defaultColumnWidth,
className,
renderCellValue,
rowIndex,
focusedCell,
onCellFocus,
interactiveCellId,
'data-test-subj': _dataTestSubj,
visibleRowIndex,
...rest
} = props;
const EuiDataGridDataRow: FunctionComponent<EuiDataGridDataRowProps> = memo(
props => {
const {
columns,
schema,
popoverContents,
columnWidths,
defaultColumnWidth,
className,
renderCellValue,
rowIndex,
focusedCellPositionInTheRow,
onCellFocus,
interactiveCellId,
'data-test-subj': _dataTestSubj,
visibleRowIndex,
...rest
} = props;

const classes = classnames('euiDataGridRow', className);
const dataTestSubj = classnames('dataGridRow', _dataTestSubj);
const classes = classnames('euiDataGridRow', className);
const dataTestSubj = classnames('dataGridRow', _dataTestSubj);

return (
<div role="row" className={classes} data-test-subj={dataTestSubj} {...rest}>
{columns.map((props, i) => {
const { id } = props;
const columnType = schema[id] ? schema[id].columnType : null;
return (
<div
role="row"
className={classes}
data-test-subj={dataTestSubj}
{...rest}>
{columns.map((props, i) => {
const { id } = props;
const columnType = schema[id] ? schema[id].columnType : null;

const isExpandable =
props.isExpandable !== undefined ? props.isExpandable : true;
const popoverContent =
popoverContents[columnType as string] || DefaultColumnFormatter;
const isExpandable =
props.isExpandable !== undefined ? props.isExpandable : true;
const popoverContent =
popoverContents[columnType as string] || DefaultColumnFormatter;

const width = columnWidths[id] || defaultColumnWidth;
const width = columnWidths[id] || defaultColumnWidth;

const isFocused =
focusedCell[0] === i && focusedCell[1] === visibleRowIndex;

return (
<EuiDataGridCell
key={`${id}-${rowIndex}`}
rowIndex={rowIndex}
visibleRowIndex={visibleRowIndex}
colIndex={i}
columnId={id}
columnType={columnType}
popoverContent={popoverContent}
width={width || undefined}
renderCellValue={renderCellValue}
onCellFocus={onCellFocus}
isFocused={isFocused}
interactiveCellId={interactiveCellId}
isExpandable={isExpandable}
/>
);
})}
</div>
);
};
return (
<EuiDataGridCell
key={`${id}-${rowIndex}`}
rowIndex={rowIndex}
visibleRowIndex={visibleRowIndex}
colIndex={i}
columnId={id}
columnType={columnType}
popoverContent={popoverContent}
width={width || undefined}
renderCellValue={renderCellValue}
onCellFocus={onCellFocus}
isFocused={focusedCellPositionInTheRow === i}
interactiveCellId={interactiveCellId}
isExpandable={isExpandable}
/>
);
})}
</div>
);
}
);

export { EuiDataGridDataRow };
3 changes: 2 additions & 1 deletion src/components/datagrid/data_grid_header_row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
EuiDataGridColumnWidths,
EuiDataGridColumn,
EuiDataGridSorting,
EuiDataGridFocusedCell,
} from './data_grid_types';
import { CommonProps } from '../common';
import { EuiDataGridColumnResizer } from './data_grid_column_resizer';
Expand All @@ -28,7 +29,7 @@ interface EuiDataGridHeaderRowPropsSpecificProps {
defaultColumnWidth?: number | null;
setColumnWidth: (columnId: string, width: number) => void;
sorting?: EuiDataGridSorting;
focusedCell: EuiDataGridDataRowProps['focusedCell'];
focusedCell: EuiDataGridFocusedCell;
setFocusedCell: EuiDataGridDataRowProps['onCellFocus'];
headerIsInteractive: boolean;
}
Expand Down
2 changes: 2 additions & 0 deletions src/components/datagrid/data_grid_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ export interface EuiDataGridInMemory {
skipColumns?: string[];
}

export type EuiDataGridFocusedCell = [number, number];

export interface EuiDataGridInMemoryValues {
[key: string]: { [key: string]: string };
}
Expand Down