Skip to content

Commit 80c86bf

Browse files
authored
fix: use Observer to check sticky bar (#1099)
* fix: use Observer to check sticky bar * add raf
1 parent 3fc8cbd commit 80c86bf

File tree

2 files changed

+42
-33
lines changed

2 files changed

+42
-33
lines changed

src/Table.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,10 @@ function Table<RecordType extends DefaultRecordType>(
363363
const fixColumn = horizonScroll && flattenColumns.some(({ fixed }) => fixed);
364364

365365
// Sticky
366-
const stickyRef = React.useRef<{ setScrollLeft: (left: number) => void }>();
366+
const stickyRef = React.useRef<{
367+
setScrollLeft: (left: number) => void;
368+
checkScrollBarVisible: () => void;
369+
}>();
367370
const { isSticky, offsetHeader, offsetSummary, offsetScroll, stickyClassName, container } =
368371
useSticky(sticky, prefixCls);
369372

@@ -486,6 +489,7 @@ function Table<RecordType extends DefaultRecordType>(
486489
};
487490

488491
const onFullTableResize = ({ width }) => {
492+
stickyRef.current?.checkScrollBarVisible();
489493
let mergedWidth = fullTableRef.current ? fullTableRef.current.offsetWidth : width;
490494
if (useInternalHooks && getContainerWidth && fullTableRef.current) {
491495
mergedWidth = getContainerWidth(fullTableRef.current, mergedWidth) || mergedWidth;
@@ -716,7 +720,6 @@ function Table<RecordType extends DefaultRecordType>(
716720
scrollBodyRef={scrollBodyRef}
717721
onScroll={onInternalScroll}
718722
container={container}
719-
data={data}
720723
/>
721724
)}
722725
</>

src/stickyScrollBar.tsx

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ import getScrollBarSize from 'rc-util/lib/getScrollBarSize';
66
import * as React from 'react';
77
import TableContext from './context/TableContext';
88
import { useLayoutState } from './hooks/useFrame';
9+
import raf from 'rc-util/lib/raf';
910

1011
interface StickyScrollBarProps {
1112
scrollBodyRef: React.RefObject<HTMLDivElement>;
1213
onScroll: (params: { scrollLeft?: number }) => void;
1314
offsetScroll: number;
1415
container: HTMLElement | Window;
15-
data?: readonly any[];
1616
}
1717

1818
const StickyScrollBar: React.ForwardRefRenderFunction<unknown, StickyScrollBarProps> = (
19-
{ scrollBodyRef, onScroll, offsetScroll, container, data },
19+
{ scrollBodyRef, onScroll, offsetScroll, container },
2020
ref,
2121
) => {
2222
const prefixCls = useContext(TableContext, 'prefixCls');
@@ -40,6 +40,14 @@ const StickyScrollBar: React.ForwardRefRenderFunction<unknown, StickyScrollBarPr
4040
x: 0,
4141
});
4242
const [isActive, setActive] = React.useState(false);
43+
const rafRef = React.useRef<number | null>(null);
44+
45+
React.useEffect(
46+
() => () => {
47+
raf.cancel(rafRef.current);
48+
},
49+
[],
50+
);
4351

4452
const onMouseUp: React.MouseEventHandler<HTMLDivElement> = () => {
4553
setActive(false);
@@ -82,30 +90,32 @@ const StickyScrollBar: React.ForwardRefRenderFunction<unknown, StickyScrollBarPr
8290
};
8391

8492
const checkScrollBarVisible = () => {
85-
if (!scrollBodyRef.current) {
86-
return;
87-
}
88-
const tableOffsetTop = getOffset(scrollBodyRef.current).top;
89-
const tableBottomOffset = tableOffsetTop + scrollBodyRef.current.offsetHeight;
90-
const currentClientOffset =
91-
container === window
92-
? document.documentElement.scrollTop + window.innerHeight
93-
: getOffset(container).top + (container as HTMLElement).clientHeight;
94-
95-
if (
96-
tableBottomOffset - getScrollBarSize() <= currentClientOffset ||
97-
tableOffsetTop >= currentClientOffset - offsetScroll
98-
) {
99-
setScrollState(state => ({
100-
...state,
101-
isHiddenScrollBar: true,
102-
}));
103-
} else {
104-
setScrollState(state => ({
105-
...state,
106-
isHiddenScrollBar: false,
107-
}));
108-
}
93+
rafRef.current = raf(() => {
94+
if (!scrollBodyRef.current) {
95+
return;
96+
}
97+
const tableOffsetTop = getOffset(scrollBodyRef.current).top;
98+
const tableBottomOffset = tableOffsetTop + scrollBodyRef.current.offsetHeight;
99+
const currentClientOffset =
100+
container === window
101+
? document.documentElement.scrollTop + window.innerHeight
102+
: getOffset(container).top + (container as HTMLElement).clientHeight;
103+
104+
if (
105+
tableBottomOffset - getScrollBarSize() <= currentClientOffset ||
106+
tableOffsetTop >= currentClientOffset - offsetScroll
107+
) {
108+
setScrollState(state => ({
109+
...state,
110+
isHiddenScrollBar: true,
111+
}));
112+
} else {
113+
setScrollState(state => ({
114+
...state,
115+
isHiddenScrollBar: false,
116+
}));
117+
}
118+
});
109119
};
110120

111121
const setScrollLeft = (left: number) => {
@@ -119,6 +129,7 @@ const StickyScrollBar: React.ForwardRefRenderFunction<unknown, StickyScrollBarPr
119129

120130
React.useImperativeHandle(ref, () => ({
121131
setScrollLeft,
132+
checkScrollBarVisible,
122133
}));
123134

124135
React.useEffect(() => {
@@ -156,11 +167,6 @@ const StickyScrollBar: React.ForwardRefRenderFunction<unknown, StickyScrollBarPr
156167
}
157168
}, [scrollState.isHiddenScrollBar]);
158169

159-
// The best way is to use ResizeObserver to detect the body height, but this way is enough
160-
React.useEffect(() => {
161-
checkScrollBarVisible();
162-
}, [data]);
163-
164170
if (bodyScrollWidth <= bodyWidth || !scrollBarWidth || scrollState.isHiddenScrollBar) {
165171
return null;
166172
}

0 commit comments

Comments
 (0)