Skip to content

Commit 87005f5

Browse files
authored
feat: Table support onScroll event (#1089)
* feat: support onScroll * test: add test case * test: fix vitest cov
1 parent 851d1eb commit 87005f5

File tree

7 files changed

+58
-12
lines changed

7 files changed

+58
-12
lines changed

src/Table.tsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ export interface TableProps<RecordType = unknown>
121121

122122
sticky?: boolean | TableSticky;
123123

124+
// Events
125+
onScroll?: React.UIEventHandler<HTMLDivElement>;
126+
124127
// =================================== Internal ===================================
125128
/**
126129
* @private Internal usage, may remove by refactor. Should always use `columns` instead.
@@ -204,6 +207,9 @@ function Table<RecordType extends DefaultRecordType>(
204207
onRow,
205208
onHeaderRow,
206209

210+
// Events
211+
onScroll,
212+
207213
// Internal
208214
internalHooks,
209215
transformColumns,
@@ -426,7 +432,7 @@ function Table<RecordType extends DefaultRecordType>(
426432
}
427433
}
428434

429-
const onScroll = useEvent(
435+
const onInternalScroll = useEvent(
430436
({ currentTarget, scrollLeft }: { currentTarget: HTMLElement; scrollLeft?: number }) => {
431437
const isRTL = direction === 'rtl';
432438
const mergedScrollLeft =
@@ -462,9 +468,14 @@ function Table<RecordType extends DefaultRecordType>(
462468
},
463469
);
464470

471+
const onBodyScroll = useEvent((e: React.UIEvent<HTMLDivElement>) => {
472+
onInternalScroll(e);
473+
onScroll?.(e);
474+
});
475+
465476
const triggerOnScroll = () => {
466477
if (horizonScroll && scrollBodyRef.current) {
467-
onScroll({ currentTarget: scrollBodyRef.current } as React.UIEvent<HTMLDivElement>);
478+
onInternalScroll({ currentTarget: scrollBodyRef.current } as React.UIEvent<HTMLDivElement>);
468479
} else {
469480
setPingedLeft(false);
470481
setPingedRight(false);
@@ -606,7 +617,7 @@ function Table<RecordType extends DefaultRecordType>(
606617
bodyContent = customizeScrollBody(mergedData, {
607618
scrollbarSize,
608619
ref: scrollBodyRef,
609-
onScroll,
620+
onScroll: onInternalScroll,
610621
});
611622

612623
headerProps.colWidths = flattenColumns.map(({ width }, index) => {
@@ -631,7 +642,7 @@ function Table<RecordType extends DefaultRecordType>(
631642
...scrollXStyle,
632643
...scrollYStyle,
633644
}}
634-
onScroll={onScroll}
645+
onScroll={onBodyScroll}
635646
ref={scrollBodyRef}
636647
className={classNames(`${prefixCls}-body`)}
637648
>
@@ -663,7 +674,7 @@ function Table<RecordType extends DefaultRecordType>(
663674
...columnContext,
664675
direction,
665676
stickyClassName,
666-
onScroll,
677+
onScroll: onInternalScroll,
667678
};
668679

669680
groupTableNode = (
@@ -700,7 +711,7 @@ function Table<RecordType extends DefaultRecordType>(
700711
ref={stickyRef}
701712
offsetScroll={offsetScroll}
702713
scrollBodyRef={scrollBodyRef}
703-
onScroll={onScroll}
714+
onScroll={onInternalScroll}
704715
container={container}
705716
data={data}
706717
/>
@@ -716,7 +727,7 @@ function Table<RecordType extends DefaultRecordType>(
716727
...scrollYStyle,
717728
}}
718729
className={classNames(`${prefixCls}-content`)}
719-
onScroll={onScroll}
730+
onScroll={onInternalScroll}
720731
ref={scrollBodyRef}
721732
>
722733
<TableComponent

src/VirtualTable/BodyGrid.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
4141
'emptyNode',
4242
'scrollX',
4343
]);
44-
const { sticky, scrollY, listItemHeight, getComponent } = useContext(StaticContext);
44+
const {
45+
sticky,
46+
scrollY,
47+
listItemHeight,
48+
getComponent,
49+
onScroll: onTablePropScroll,
50+
} = useContext(StaticContext);
4551

4652
// =========================== Ref ============================
4753
const listRef = React.useRef<ListRef>();
@@ -233,6 +239,7 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
233239
scrollLeft: x,
234240
});
235241
}}
242+
onScroll={onTablePropScroll}
236243
extraRender={extraRender}
237244
>
238245
{(item, index, itemProps) => {

src/VirtualTable/context.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export interface StaticContextProps {
66
listItemHeight: number;
77
sticky: boolean | TableSticky;
88
getComponent: GetComponent;
9+
onScroll?: React.UIEventHandler<HTMLDivElement>;
910
}
1011

1112
export const StaticContext = createContext<StaticContextProps>(null);

src/VirtualTable/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function VirtualTable<RecordType>(props: VirtualTableProps<RecordType>, ref: Rea
3333
className,
3434
listItemHeight,
3535
components,
36+
onScroll,
3637
} = props;
3738

3839
let { x: scrollX, y: scrollY } = scroll || {};
@@ -59,10 +60,13 @@ function VirtualTable<RecordType>(props: VirtualTableProps<RecordType>, ref: Rea
5960
(path, defaultComponent) => getValue(components, path) || defaultComponent,
6061
);
6162

63+
// Memo this
64+
const onInternalScroll = useEvent(onScroll);
65+
6266
// ========================= Context ==========================
6367
const context = React.useMemo(
64-
() => ({ sticky, scrollY, listItemHeight, getComponent }),
65-
[sticky, scrollY, listItemHeight, getComponent],
68+
() => ({ sticky, scrollY, listItemHeight, getComponent, onScroll: onInternalScroll }),
69+
[sticky, scrollY, listItemHeight, getComponent, onInternalScroll],
6670
);
6771

6872
// ========================== Render ==========================

tests/Table.spec.jsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Table, { INTERNAL_COL_DEFINE } from '../src';
66
import BodyRow from '../src/Body/BodyRow';
77
import Cell from '../src/Cell';
88
import { INTERNAL_HOOKS } from '../src/constant';
9+
import { fireEvent, render } from '@testing-library/react';
910

1011
describe('Table.Basic', () => {
1112
const data = [
@@ -1319,4 +1320,17 @@ describe('Table.Basic', () => {
13191320
.props().style.width + wrapper.find('col').last().props().style.width,
13201321
).toEqual(width);
13211322
});
1323+
1324+
it('onScroll event', () => {
1325+
const onScroll = vi.fn();
1326+
const wrapper = render(
1327+
createTable({
1328+
onScroll,
1329+
scroll: { x: 100, y: 100 },
1330+
}),
1331+
);
1332+
1333+
fireEvent.scroll(wrapper.container.querySelector('.rc-table-body'));
1334+
expect(onScroll).toHaveBeenCalled();
1335+
});
13221336
});

tests/Virtual.spec.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,4 +433,14 @@ describe('Table.Virtual', () => {
433433
'my-cell',
434434
);
435435
});
436+
437+
it('onScroll event should work', async () => {
438+
const onScroll = vi.fn();
439+
const { container } = getTable({ onScroll });
440+
441+
await waitFakeTimer();
442+
443+
fireEvent.scroll(container.querySelector('.rc-table-tbody-virtual-holder')!);
444+
expect(onScroll).toHaveBeenCalled();
445+
});
436446
});

vitest.config.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ export default defineConfig({
66
},
77
test: {
88
include: ['**/tests/*.spec.*'],
9-
exclude: ['**/coverage/**'],
109
globals: true,
1110
setupFiles: './tests/setup.ts',
1211
environment: 'jsdom',
1312
coverage: {
14-
exclude: ['**/docs/**', '**/__mocks__/**'],
13+
exclude: ['**/docs/**', '**/__mocks__/**', '**/coverage/**'],
1514
},
1615
},
1716
});

0 commit comments

Comments
 (0)