From 87b9d87db98462c66c9658e59ff369a9226bae6b Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Sat, 4 Apr 2020 07:49:39 +0200 Subject: [PATCH] optimalization of grid rendering --- packages/web/src/datagrid/DataGridCore.js | 14 +++++--- packages/web/src/datagrid/DataGridRow.js | 35 +++++++++++++++---- .../src/datagrid/{gridutil.js => gridutil.ts} | 10 ++++++ 3 files changed, 47 insertions(+), 12 deletions(-) rename packages/web/src/datagrid/{gridutil.js => gridutil.ts} (92%) diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index 8dec22366..d27fa1900 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -24,7 +24,7 @@ import { import keycodes from '../utility/keycodes'; import InplaceEditor from './InplaceEditor'; import DataGridRow from './DataGridRow'; -import { countColumnSizes, countVisibleRealColumns } from './gridutil'; +import { countColumnSizes, countVisibleRealColumns, filterCellForRow, filterCellsForRow } from './gridutil'; import useModalState from '../modals/useModalState'; import ConfirmSqlModal from '../modals/ConfirmSqlModal'; import { @@ -100,7 +100,7 @@ const FocusField = styled.input` /** @param props {import('./types').DataGridProps} */ export default function DataGridCore(props) { const { conid, database, display, changeSetState, dispatchChangeSet, tabVisible } = props; - const columns = display.getGridColumns(); + const columns = React.useMemo(() => display.getGridColumns(), [display]); // usePropsCompare(props); @@ -135,7 +135,7 @@ export default function DataGridCore(props) { // const [inplaceEditorChangedOnCreate, setInplaceEditorChangedOnCreate] = React.useState(false); const changeSet = changeSetState.value; - const setChangeSet = value => dispatchChangeSet({ type: 'set', value }); + const setChangeSet = React.useCallback(value => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]); const changeSetRef = React.useRef(changeSet); @@ -238,6 +238,8 @@ export default function DataGridCore(props) { return {}; }, {}); + // usePropsCompare({ loadedRows, columns, containerWidth, display }); + const columnSizes = React.useMemo(() => countColumnSizes(loadedRows, columns, containerWidth, display), [ loadedRows, columns, @@ -304,6 +306,8 @@ export default function DataGridCore(props) { // [tableElement, currentCell] // ); + // usePropsCompare({ columnSizes, firstVisibleColumnScrollIndex, gridScrollAreaWidth, columns }); + const visibleRealColumns = React.useMemo( () => countVisibleRealColumns(columnSizes, firstVisibleColumnScrollIndex, gridScrollAreaWidth, columns), [columnSizes, firstVisibleColumnScrollIndex, gridScrollAreaWidth, columns] @@ -878,13 +882,13 @@ export default function DataGridCore(props) { inplaceEditorState={inplaceEditorState} dispatchInsplaceEditor={dispatchInsplaceEditor} autofillSelectedCells={autofillSelectedCells} - selectedCells={selectedCells} + selectedCells={filterCellsForRow(selectedCells, firstVisibleRowScrollIndex + index)} insertedRowIndex={ firstVisibleRowScrollIndex + index >= loadedRows.length ? firstVisibleRowScrollIndex + index - loadedRows.length : null } - autofillMarkerCell={autofillMarkerCell} + autofillMarkerCell={filterCellForRow(autofillMarkerCell, firstVisibleRowScrollIndex + index)} changeSet={changeSet} setChangeSet={setChangeSet} display={display} diff --git a/packages/web/src/datagrid/DataGridRow.js b/packages/web/src/datagrid/DataGridRow.js index 4a6247fae..dd10015fb 100644 --- a/packages/web/src/datagrid/DataGridRow.js +++ b/packages/web/src/datagrid/DataGridRow.js @@ -15,6 +15,7 @@ import { getFilterType } from '@dbgate/filterparser'; import { findExistingChangeSetItem } from '@dbgate/datalib'; import keycodes from '../utility/keycodes'; import InplaceEditor from './InplaceEditor'; +import usePropsCompare from '../utility/usePropsCompare'; const TableBodyCell = styled.td` font-weight: normal; @@ -40,12 +41,12 @@ const TableBodyCell = styled.td` color: white;`} ${props => - props.isModifiedRow && - !props.isInsertedRow && - !props.isSelected && - !props.isAutofillSelected && - !props.isModifiedCell && - ` + props.isModifiedRow && + !props.isInsertedRow && + !props.isSelected && + !props.isAutofillSelected && + !props.isModifiedCell && + ` background-color: #FFFFDB;`} ${props => !props.isSelected && @@ -126,6 +127,7 @@ function CellFormattedValue({ value }) { } function cellIsSelected(row, col, selectedCells) { + if (!selectedCells) return false; for (const [selectedRow, selectedCol] of selectedCells) { if (row == selectedRow && col == selectedCol) return true; if (selectedRow == 'header' && col == selectedCol) return true; @@ -135,7 +137,7 @@ function cellIsSelected(row, col, selectedCells) { return false; } -export default function DataGridRow({ +function DataGridRow({ rowHeight, rowIndex, visibleRealColumns, @@ -150,7 +152,24 @@ export default function DataGridRow({ selectedCells, autofillSelectedCells, }) { + // usePropsCompare({ + // rowHeight, + // rowIndex, + // visibleRealColumns, + // inplaceEditorState, + // dispatchInsplaceEditor, + // row, + // display, + // changeSet, + // setChangeSet, + // insertedRowIndex, + // autofillMarkerCell, + // selectedCells, + // autofillSelectedCells, + // }); + // console.log('RENDER ROW', rowIndex); + const rowDefinition = display.getChangeSetRow(row, insertedRowIndex); const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(changeSet, rowDefinition); const rowUpdated = matchedChangeSetItem ? { ...row, ...matchedChangeSetItem.fields } : row; @@ -214,3 +233,5 @@ export default function DataGridRow({ ); } + +export default React.memo(DataGridRow); diff --git a/packages/web/src/datagrid/gridutil.js b/packages/web/src/datagrid/gridutil.ts similarity index 92% rename from packages/web/src/datagrid/gridutil.js rename to packages/web/src/datagrid/gridutil.ts index 457410295..4891a0832 100644 --- a/packages/web/src/datagrid/gridutil.js +++ b/packages/web/src/datagrid/gridutil.ts @@ -1,4 +1,5 @@ import { SeriesSizes } from './SeriesSizes'; +import { CellAddress } from './selection'; export function countColumnSizes(loadedRows, columns, containerWidth, display) { let canvas = document.createElement('canvas'); @@ -105,3 +106,12 @@ export function countVisibleRealColumns(columnSizes, firstVisibleColumnScrollInd } return realColumns; } + +export function filterCellForRow(cell, row: number): CellAddress | null { + return cell && cell[0] == row ? cell : null; +} + +export function filterCellsForRow(cells, row: number): CellAddress[] | null { + const res = (cells || []).filter(x => x[0] == row); + return res.length > 0 ? res : null; +}