Skip to content

Commit

Permalink
fix: fixed virtualized Table List ref is null bug #2305 (#2319)
Browse files Browse the repository at this point in the history
* fix: fixed virtualized Table List ref is null bug #2305
* fix: table story import error
---------

Co-authored-by: shijia.me <[email protected]>
Co-authored-by: pointhalo <[email protected]>
Co-authored-by: 代强 <[email protected]>
Co-authored-by: pointhalo <[email protected]>
  • Loading branch information
5 people authored Jul 12, 2024
1 parent f131257 commit cc3d610
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 21 deletions.
8 changes: 8 additions & 0 deletions cypress/e2e/table.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@ describe('table', () => {
cy.get('tbody .semi-table-row-section').eq(0).should('have.class', 'test-group');
});


it('test virtualized table ref', () => {
cy.visit('http://localhost:6006/iframe.html?id=table--fixed-virtualized-ref&viewMode=story');
cy.get('.semi-button').eq(0).click();
cy.wait(300);
cy.get('.semi-table-row-cell').should('contain.text', 'Semi Design 设计稿20.fig');
});

it('test rowSelection onCell and onHeaderCell', () => {
cy.visit('http://localhost:6006/iframe.html?id=table--row-selection-on-cell&viewMode=story');
cy.get('.test-th').should('have.attr', 'style').should('contain', 'background: blue');
Expand Down
2 changes: 1 addition & 1 deletion packages/semi-foundation/slider/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface SliderProps{
handleDot?: {
size?: string;
color?: string
} & ({
} | ({
size?: string;
color?: string
}[])
Expand Down
22 changes: 14 additions & 8 deletions packages/semi-ui/slider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
const offsetParentRect = this.sliderEl.current.offsetParent?.getBoundingClientRect();

const offset = {
x: offsetParentRect ? (rect.left - offsetParentRect.left): this.sliderEl.current.offsetLeft,
x: offsetParentRect ? (rect.left - offsetParentRect.left) : this.sliderEl.current.offsetLeft,
y: offsetParentRect ? (rect.top - offsetParentRect.top) : this.sliderEl.current.offsetTop,
};
return {
Expand Down Expand Up @@ -333,7 +333,13 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
'aria-disabled': disabled
};
vertical && Object.assign(commonAria, { 'aria-orientation': 'vertical' });

const handleDot = this.props.handleDot as {
size?: string;
color?: string
} & ({
size?: string;
color?: string
}[]);
const handleContents = !range ? (
<Tooltip
content={tipChildren.min}
Expand Down Expand Up @@ -387,9 +393,9 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
aria-valuemax={max}
aria-valuemin={min}
>
{this.props.handleDot && <div className={cssClasses.HANDLE_DOT} style={{
...(this.props.handleDot?.size ? { width: this.props.handleDot.size, height: this.props.handleDot.size } : {}),
...(this.props.handleDot?.color ? { backgroundColor: this.props.handleDot.color } : {}),
{handleDot && <div className={cssClasses.HANDLE_DOT} style={{
...(handleDot?.size ? { width: handleDot.size, height: handleDot.size } : {}),
...(handleDot?.color ? { backgroundColor: handleDot.color } : {}),
}} />}
</span>
</Tooltip>
Expand Down Expand Up @@ -445,9 +451,9 @@ export default class Slider extends BaseComponent<SliderProps, SliderState> {
aria-valuemax={currentValue[1]}
aria-valuemin={min}
>
{this.props.handleDot?.[0] && <div className={cssClasses.HANDLE_DOT} style={{
...(this.props.handleDot[0]?.size ? { width: this.props.handleDot[0].size, height: this.props.handleDot[0].size } : {}),
...(this.props.handleDot[0]?.color ? { backgroundColor: this.props.handleDot[0].color } : {}),
{handleDot?.[0] && <div className={cssClasses.HANDLE_DOT} style={{
...(handleDot[0]?.size ? { width: handleDot[0].size, height: handleDot[0].size } : {}),
...(handleDot[0]?.color ? { backgroundColor: handleDot[0].color } : {}),
}} />}
</span>
</Tooltip>
Expand Down
25 changes: 15 additions & 10 deletions packages/semi-ui/table/Body/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
};

this.listRef = React.createRef();
const { getVirtualizedListRef, flattenedColumns, getCellWidths } = context;
if (getVirtualizedListRef) {
if (props.virtualized) {
getVirtualizedListRef(this.listRef);
} else {
console.warn('getVirtualizedListRef only works with virtualized. ' +
'See https://semi.design/en-US/show/table for more information.');
}
}
const { flattenedColumns, getCellWidths } = context;
this.foundation = new BodyFoundation(this.adapter);
this.flattenedColumns = flattenedColumns;
this.cellWidths = getCellWidths(flattenedColumns);
Expand Down Expand Up @@ -246,6 +238,19 @@ class Body extends BaseComponent<BodyProps, BodyState> {
}
};

setListRef = (listInstance: List) => {
this.listRef.current = listInstance;
const { getVirtualizedListRef } = this.context;
if (getVirtualizedListRef) {
if (this.props.virtualized) {
getVirtualizedListRef(this.listRef);
} else {
console.warn('getVirtualizedListRef only works with virtualized. ' +
'See https://semi.design/en-US/show/table for more information.');
}
}
};

itemSize = (index: number) => {
const { virtualized, size: tableSize } = this.props;
const { virtualizedData } = this.state;
Expand Down Expand Up @@ -432,7 +437,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
initialScrollOffset={this.state.cache.virtualizedScrollTop}
onScroll={this.handleVirtualizedScroll}
onItemsRendered={this.onItemsRendered}
ref={this.listRef}
ref={this.setListRef}
className={wrapCls}
outerRef={this.forwardRef}
height={virtualizedData?.length ? y : 0}
Expand Down
1 change: 1 addition & 0 deletions packages/semi-ui/table/_story/table.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export {
FixedRowSelectionEmpty,
DndKitDrag,
FixedOnGroupedRowClassName,
FixedVirtualizedRef,
RowSelectionOnCell
} from './v2';
export { default as FixSelectAll325 } from './Demos/rowSelection';
Expand Down
118 changes: 118 additions & 0 deletions packages/semi-ui/table/_story/v2/FixedVirtualizedRef/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, { useRef, useState, useEffect } from "react";
import * as dateFns from 'date-fns';
import { VariableSizeList } from 'react-window';

import { Avatar, Button, Table } from "../../../../index";
import { ColumnProps } from "../../../interface";

export default function VirtualizedFixedDemo() {
const DAY = 24 * 60 * 60 * 1000;
let virtualizedListRef = useRef<VariableSizeList>();
const [scroll, setScroll] = useState({});
const style = { width: 750, margin: '0 auto' };
const getData = () => {
const data = [];
for (let i = 0; i < 1000; i++) {
const isSemiDesign = i % 2 === 0;
const randomNumber = (i * 1000) % 199;
data.push({
key: '' + i,
name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi D2C 设计稿${i}.fig`,
owner: isSemiDesign ? '姜鹏志' : '郝宣',
size: randomNumber,
updateTime: new Date('2024-06-24').valueOf() + randomNumber * DAY,
avatarBg: isSemiDesign ? 'grey' : 'red',
});
}
return data;
};

const data = getData();
const columns: ColumnProps[] = [
{
title: '标题',
dataIndex: 'name',
width: 200,
fixed: true,
render: (text, record, index) => {
return <div>{text}</div>;
},
filters: [
{
text: 'Semi Design 设计稿',
value: 'Semi Design 设计稿',
},
{
text: 'Semi D2C 设计稿',
value: 'Semi D2C 设计稿',
},
],
onCell: (_, index) => {
return ({
className: `row-${index}`
});
},
onFilter: (value, record) => record.name.includes(value),
},
{
title: '大小',
dataIndex: 'size',
width: 150,
sorter: (a, b) => (a.size - b.size > 0 ? 1 : -1),
render: text => `${text} KB`,
},
{
title: '所有者',
dataIndex: 'owner',
render: (text, record, index) => {
return (
<div>
<Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
{typeof text === 'string' && text.slice(0, 1)}
</Avatar>
{text}
</div>
);
},
},
{
title: '更新日期',
dataIndex: 'updateTime',
fixed: 'right',
width: 150,
sorter: (a, b) => (a.updateTime - b.updateTime > 0 ? 1 : -1),
render: value => {
return dateFns.format(new Date(value), 'yyyy-MM-dd');
},
},
];

useEffect(() => {
setScroll({
y: 400, x: 900
});
}, []);

const handleClick = () => {
console.log('ref', virtualizedListRef);
virtualizedListRef.current && virtualizedListRef.current.scrollToItem(20);
};

return (
<>
<Button onClick={handleClick}>Scroll to 20</Button>
<Table
pagination={false}
columns={columns}
dataSource={data}
scroll={scroll}
style={style}
virtualized
getVirtualizedListRef={ref => {
console.log('ref', ref);
virtualizedListRef = ref;
}}
/>
</>
);
}
1 change: 1 addition & 0 deletions packages/semi-ui/table/_story/v2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export { default as FixedDefaultExpandedGroupedRows } from './FixedExpandGroupRo
export { default as FixedRowSelectionEmpty } from './FixedRowSelectionEmpty';
export { default as DndKitDrag } from './DndKitDrag';
export { default as FixedOnGroupedRowClassName } from './FixedOnGroupedRowClassName';
export { default as FixedVirtualizedRef } from './FixedVirtualizedRef';
export { default as RowSelectionOnCell } from './RowSelectionOnCell';
4 changes: 2 additions & 2 deletions packages/semi-ui/table/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type {
BaseIncludeGroupRecord,
BaseEllipsis
} from '@douyinfe/semi-foundation/table/foundation';
import type { ScrollDirection, CSSDirection } from 'react-window';
import type { ScrollDirection, CSSDirection, VariableSizeList } from 'react-window';
import type { ColumnFilterProps } from './ColumnFilter';

export interface TableProps<RecordType extends Record<string, any> = any> extends BaseProps {
Expand Down Expand Up @@ -277,7 +277,7 @@ export type ExpandIcon = ((expanded?: boolean) => React.ReactNode) | React.React
export type ExpandedRowRender<RecordType> = (record?: RecordType, index?: number, expanded?: boolean) => React.ReactNode;
export type Footer<RecordType> = ReactNode | ((pageData?: RecordType[]) => React.ReactNode);
export type FormatPageText = ((pageInfo?: { currentStart?: number; currentEnd?: number; total?: number }) => React.ReactNode) | boolean;
export type GetVirtualizedListRef = (ref: MutableRefObject<any>) => void;
export type GetVirtualizedListRef = (ref: MutableRefObject<VariableSizeList>) => void;
export type GroupByFunction<RecordType> = BaseGroupByFn<RecordType>;
export type GroupBy<RecordType> = BaseGroupBy<RecordType>;
export type Size = ArrayElement<typeof strings.SIZES>;
Expand Down

0 comments on commit cc3d610

Please sign in to comment.