mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
CB-5703 refactor: optimize data grid onScroll handler (#3071)
handleScroll in DataGrid entails small performance degradation due to el.scrollTop, el.clientHeight, el.scrollHeight calls and hence reflow of layout, more on that here: https://gist.github.com/paulirish/5d52fb081b3570c81e3a/565c05680b27c9cfd9f5e971d295cd558c3e1843 What is done: 1. throttle added to not fire handleScroll on every render, because the main goal of that function is to detect when a user approaches the end of a page = reduce number of calls 2. Inside the handler the code was refactored in a way that we get scrollTop only once to calculate toBottom and inverse the clause logic and replace early return (!A || !B) with a clause with (A && B) logic to not check B on every call which is also triggering reflow. Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import { useService } from '@cloudbeaver/core-di';
|
||||
import { EventContext, EventStopPropagationFlag } from '@cloudbeaver/core-events';
|
||||
import { Executor } from '@cloudbeaver/core-executor';
|
||||
import { ClipboardService } from '@cloudbeaver/core-ui';
|
||||
import { throttle } from '@cloudbeaver/core-utils';
|
||||
import { useCaptureViewContext } from '@cloudbeaver/core-view';
|
||||
import { type CellSelectArgs, DataGrid, type DataGridHandle, type Position } from '@cloudbeaver/plugin-data-grid';
|
||||
import {
|
||||
@@ -52,8 +53,8 @@ interface IInnerState {
|
||||
}
|
||||
|
||||
function isAtBottom(event: React.UIEvent<HTMLDivElement>): boolean {
|
||||
const target = event.target as HTMLDivElement;
|
||||
return target.clientHeight + target.scrollTop + 100 > target.scrollHeight;
|
||||
const { clientHeight, scrollTop, scrollHeight } = event.target as HTMLDivElement;
|
||||
return clientHeight + scrollTop + 100 > scrollHeight;
|
||||
}
|
||||
|
||||
const rowHeight = 25;
|
||||
@@ -410,23 +411,21 @@ export const DataGridTable = observer<IDataPresentationProps>(function DataGridT
|
||||
};
|
||||
|
||||
const handleScroll = useCallback(
|
||||
async (event: React.UIEvent<HTMLDivElement>) => {
|
||||
const target = event.target as HTMLDivElement;
|
||||
const toBottom = target.scrollTop > innerState.lastScrollTop;
|
||||
throttle(async (event: React.UIEvent<HTMLDivElement>) => {
|
||||
const scrollTop = (event.target as HTMLDivElement).scrollTop;
|
||||
const toBottom = scrollTop > innerState.lastScrollTop;
|
||||
|
||||
innerState.lastScrollTop = target.scrollTop;
|
||||
innerState.lastScrollTop = scrollTop;
|
||||
|
||||
if (!toBottom || !isAtBottom(event)) {
|
||||
return;
|
||||
if (toBottom && isAtBottom(event)) {
|
||||
const result = model.source.getResult(resultIndex);
|
||||
if (result?.loadedFully) {
|
||||
return;
|
||||
}
|
||||
|
||||
await model.requestDataPortion(0, model.countGain + model.source.count);
|
||||
}
|
||||
|
||||
const result = model.source.getResult(resultIndex);
|
||||
if (result?.loadedFully) {
|
||||
return;
|
||||
}
|
||||
|
||||
await model.requestDataPortion(0, model.countGain + model.source.count);
|
||||
},
|
||||
}, 200),
|
||||
[model, resultIndex],
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user