Skip to content

Commit 2c66f7b

Browse files
committed
fix: scrolling performance optimizations for table
1 parent 9a13999 commit 2c66f7b

File tree

2 files changed

+67
-21
lines changed

2 files changed

+67
-21
lines changed

src/components/PaginatedTable/PaginatedTable.tsx

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,17 @@ export const PaginatedTable = <T, F>({
9999
[onDataFetched, setFoundEntities, setIsInitialLoad, setTotalEntities],
100100
);
101101

102+
// Set will-change: transform on scroll container if not already set
103+
React.useLayoutEffect(() => {
104+
const scrollContainer = scrollContainerRef.current;
105+
if (scrollContainer) {
106+
const computedStyle = window.getComputedStyle(scrollContainer);
107+
if (computedStyle.willChange !== 'transform') {
108+
scrollContainer.style.willChange = 'transform';
109+
}
110+
}
111+
}, [scrollContainerRef.current]);
112+
102113
// Reset table on initialization and filters change
103114
React.useLayoutEffect(() => {
104115
const defaultTotal = initialEntitiesCount || 0;
@@ -110,26 +121,61 @@ export const PaginatedTable = <T, F>({
110121
}, [initialEntitiesCount, setTotalEntities, setFoundEntities, setIsInitialLoad]);
111122

112123
const renderChunks = () => {
113-
return activeChunks.map((isActive, index) => (
114-
<TableChunk<T, F>
115-
key={index}
116-
id={index}
117-
calculatedCount={index === activeChunks.length - 1 ? lastChunkSize : chunkSize}
118-
chunkSize={chunkSize}
119-
rowHeight={rowHeight}
120-
columns={columns}
121-
fetchData={fetchData}
122-
filters={filters}
123-
tableName={tableName}
124-
sortParams={sortParams}
125-
getRowClassName={getRowClassName}
126-
renderErrorMessage={renderErrorMessage}
127-
renderEmptyDataMessage={renderEmptyDataMessage}
128-
onDataFetched={handleDataFetched}
129-
isActive={isActive}
130-
keepCache={keepCache}
131-
/>
132-
));
124+
const chunks: React.ReactElement[] = [];
125+
let i = 0;
126+
127+
while (i < activeChunks.length) {
128+
const isActive = activeChunks[i];
129+
130+
if (isActive) {
131+
// Render active chunk normally
132+
chunks.push(
133+
<TableChunk<T, F>
134+
key={i}
135+
id={i}
136+
calculatedCount={i === activeChunks.length - 1 ? lastChunkSize : chunkSize}
137+
chunkSize={chunkSize}
138+
rowHeight={rowHeight}
139+
columns={columns}
140+
fetchData={fetchData}
141+
filters={filters}
142+
tableName={tableName}
143+
sortParams={sortParams}
144+
getRowClassName={getRowClassName}
145+
renderErrorMessage={renderErrorMessage}
146+
renderEmptyDataMessage={renderEmptyDataMessage}
147+
onDataFetched={handleDataFetched}
148+
isActive={isActive}
149+
keepCache={keepCache}
150+
/>,
151+
);
152+
i++;
153+
} else {
154+
// Find consecutive inactive chunks and merge them
155+
const startIndex = i;
156+
let totalHeight = 0;
157+
158+
while (i < activeChunks.length && !activeChunks[i]) {
159+
const currentChunkSize =
160+
i === activeChunks.length - 1 ? lastChunkSize : chunkSize;
161+
totalHeight += currentChunkSize * rowHeight;
162+
i++;
163+
}
164+
165+
// Render merged empty tbody for consecutive inactive chunks
166+
chunks.push(
167+
<tbody
168+
key={`merged-${startIndex}-${i - 1}`}
169+
style={{
170+
height: `${totalHeight}px`,
171+
display: 'block',
172+
}}
173+
/>,
174+
);
175+
}
176+
}
177+
178+
return chunks;
133179
};
134180

135181
const renderTable = () => (

src/components/PaginatedTable/useScrollBasedChunks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface UseScrollBasedChunksProps {
1111
overscanCount?: number;
1212
}
1313

14-
const DEFAULT_OVERSCAN_COUNT = 1;
14+
const DEFAULT_OVERSCAN_COUNT = 2;
1515

1616
export const useScrollBasedChunks = ({
1717
scrollContainerRef,

0 commit comments

Comments
 (0)