Skip to content

Commit 7fa4b93

Browse files
committed
fix: avoid table jitter casued by changes in the first row
1 parent c2ce7ce commit 7fa4b93

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

src/List.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type { ExtraRenderInfo, GetKey, RenderFunc, SharedConfig } from './interf
2222
import type { ScrollBarDirectionType, ScrollBarRef } from './ScrollBar';
2323
import ScrollBar from './ScrollBar';
2424
import { getSpinSize } from './utils/scrollbarUtil';
25+
import { debounce } from './utils/debounce';
2526

2627
const EMPTY_DATA = [];
2728

@@ -271,10 +272,15 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
271272
rangeRef.current.start = start;
272273
rangeRef.current.end = end;
273274

275+
const isScrollingRef = useRef(false);
274276
// When scroll up, first visible item get real height may not same as `itemHeight`,
275277
// Which will make scroll jump.
276278
// Let's sync scroll top to avoid jump
277279
React.useLayoutEffect(() => {
280+
// When the `scrollHeight` change is not caused by scrolling,
281+
// end the function execution avoiding table jitter caused by changes in the first row
282+
if (!isScrollingRef.current) return;
283+
278284
const changedRecord = heights.getRecord();
279285
if (changedRecord.size === 1) {
280286
const recordKey = Array.from(changedRecord)[0];
@@ -377,6 +383,9 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
377383
}
378384
}
379385

386+
const toggleScrollStatus = React.useCallback(debounce(() => {
387+
isScrollingRef.current = false;
388+
}, 100), []);
380389
// When data size reduce. It may trigger native scroll event back to fit scroll position
381390
function onFallbackScroll(e: React.UIEvent<HTMLDivElement>) {
382391
const { scrollTop: newScrollTop } = e.currentTarget;
@@ -387,6 +396,10 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
387396
// Trigger origin onScroll
388397
onScroll?.(e);
389398
triggerScroll();
399+
// Set the scroll status to `true`
400+
isScrollingRef.current = true;
401+
// Set the scroll status to `false` after scrolling ends
402+
toggleScrollStatus();
390403
}
391404

392405
const keepInHorizontalRange = (nextOffsetLeft: number) => {

src/utils/debounce.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function debounce(fn: (...args) => void, delay: number = 300) {
2+
let timer;
3+
return function (...args) {
4+
if (timer) clearTimeout(timer);
5+
timer = setTimeout(() => {
6+
fn.apply(this, args);
7+
timer = null;
8+
}, delay);
9+
}
10+
}

0 commit comments

Comments
 (0)