Skip to content

Commit ec4ac24

Browse files
committed
test: infinite scroll virtualization fix
1 parent dd7f5cd commit ec4ac24

File tree

1 file changed

+48
-30
lines changed
  • src/features/dashboard/templates/builds

1 file changed

+48
-30
lines changed

src/features/dashboard/templates/builds/table.tsx

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,14 @@ const BuildsTable = () => {
144144
})
145145
}, [builds, runningStatusesData])
146146

147-
// virtualization - account for loader rows only when loading
148-
const showPreviousLoader = isFetchingPreviousPage
149-
const showNextLoader = isFetchingNextPage
147+
// virtualization - always include placeholder rows when more pages exist
148+
// this ensures scroll position stays stable when new data loads
149+
const hasPreviousRow = hasPreviousPage
150+
const hasNextRow = hasNextPage
150151
const rowCount =
151152
buildsWithLiveStatus.length +
152-
(showPreviousLoader ? 1 : 0) +
153-
(showNextLoader ? 1 : 0)
153+
(hasPreviousRow ? 1 : 0) +
154+
(hasNextRow ? 1 : 0)
154155

155156
const virtualizer = useVirtualizer({
156157
count: rowCount,
@@ -168,18 +169,16 @@ const BuildsTable = () => {
168169
(virtualRows[virtualRows.length - 1]?.end ?? 0)
169170
: 0
170171

171-
// auto-fetch when scrolling near edges
172+
// auto-fetch when scrolling near edges (when placeholder row becomes visible)
172173
useEffect(() => {
173174
if (!hasNextPage || isFetchingNextPage) return
174175

175176
const lastVirtualRow = virtualRows[virtualRows.length - 1]
176177
if (!lastVirtualRow) return
177178

178-
const lastDataIndex = showPreviousLoader
179-
? lastVirtualRow.index - 1
180-
: lastVirtualRow.index
181-
182-
if (lastDataIndex >= buildsWithLiveStatus.length - 1) {
179+
// check if the "load more" placeholder row is visible
180+
const loadMoreRowIndex = buildsWithLiveStatus.length + (hasPreviousRow ? 1 : 0)
181+
if (lastVirtualRow.index >= loadMoreRowIndex) {
183182
fetchNextPage()
184183
}
185184
}, [
@@ -188,7 +187,7 @@ const BuildsTable = () => {
188187
isFetchingNextPage,
189188
buildsWithLiveStatus.length,
190189
fetchNextPage,
191-
showPreviousLoader,
190+
hasPreviousRow,
192191
])
193192

194193
useEffect(() => {
@@ -197,19 +196,15 @@ const BuildsTable = () => {
197196
const firstVirtualRow = virtualRows[0]
198197
if (!firstVirtualRow) return
199198

200-
const firstDataIndex = showPreviousLoader
201-
? firstVirtualRow.index - 1
202-
: firstVirtualRow.index
203-
204-
if (firstDataIndex <= 0) {
199+
// check if the "load previous" placeholder row is visible (index 0)
200+
if (firstVirtualRow.index === 0) {
205201
fetchPreviousPage()
206202
}
207203
}, [
208204
virtualRows,
209205
hasPreviousPage,
210206
isFetchingPreviousPage,
211207
fetchPreviousPage,
212-
showPreviousLoader,
213208
])
214209

215210
// UI state
@@ -279,31 +274,54 @@ const BuildsTable = () => {
279274
)}
280275

281276
{virtualRows.map((virtualRow) => {
282-
const isPreviousLoaderRow =
283-
showPreviousLoader && virtualRow.index === 0
284-
const isNextLoaderRow =
285-
showNextLoader &&
277+
const isPreviousPlaceholder =
278+
hasPreviousRow && virtualRow.index === 0
279+
const isNextPlaceholder =
280+
hasNextRow &&
286281
virtualRow.index ===
287-
buildsWithLiveStatus.length + (showPreviousLoader ? 1 : 0)
288-
const buildIndex = showPreviousLoader
282+
buildsWithLiveStatus.length + (hasPreviousRow ? 1 : 0)
283+
const buildIndex = hasPreviousRow
289284
? virtualRow.index - 1
290285
: virtualRow.index
291286
const build = buildsWithLiveStatus[buildIndex]
292287

293-
if (isPreviousLoaderRow || isNextLoaderRow) {
288+
if (isPreviousPlaceholder) {
289+
return (
290+
<TableRow
291+
key="placeholder-prev"
292+
style={{ height: ROW_HEIGHT }}
293+
>
294+
<TableCell
295+
colSpan={6}
296+
className="text-start text-fg-tertiary"
297+
>
298+
{isFetchingPreviousPage && (
299+
<span className="flex items-center gap-2">
300+
<Loader variant="slash" size="sm" />
301+
Loading...
302+
</span>
303+
)}
304+
</TableCell>
305+
</TableRow>
306+
)
307+
}
308+
309+
if (isNextPlaceholder) {
294310
return (
295311
<TableRow
296-
key={isPreviousLoaderRow ? 'loader-prev' : 'loader-next'}
312+
key="placeholder-next"
297313
style={{ height: ROW_HEIGHT }}
298314
>
299315
<TableCell
300316
colSpan={6}
301317
className="text-start text-fg-tertiary"
302318
>
303-
<span className="flex items-center gap-2">
304-
<Loader variant="slash" size="sm" />
305-
Loading...
306-
</span>
319+
{isFetchingNextPage && (
320+
<span className="flex items-center gap-2">
321+
<Loader variant="slash" size="sm" />
322+
Loading...
323+
</span>
324+
)}
307325
</TableCell>
308326
</TableRow>
309327
)

0 commit comments

Comments
 (0)