Browse Source

fix(table): expanded row re-render #686 (#689)

走鹃 3 years ago
parent
commit
ba1406378a

+ 15 - 4
packages/semi-ui/table/Body/index.tsx

@@ -89,6 +89,8 @@ export interface BodyState {
 
 export interface BodyContext {
     getVirtualizedListRef: GetVirtualizedListRef;
+    flattenedColumns: ColumnProps[];
+    getCellWidths: (flattenedColumns: ColumnProps[]) => number[];
 }
 
 class Body extends BaseComponent<BodyProps, BodyState> {
@@ -128,6 +130,8 @@ class Body extends BaseComponent<BodyProps, BodyState> {
     listRef: React.MutableRefObject<any>;
     observer: ResizeObserver;
     foundation: BodyFoundation;
+    cellWidths: number[];
+    flattenedColumns: ColumnProps[];
     constructor(props: BodyProps, context: BodyContext) {
         super(props);
         this.ref = React.createRef();
@@ -142,7 +146,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
         };
 
         this.listRef = React.createRef();
-        const { getVirtualizedListRef } = context;
+        const { getVirtualizedListRef, flattenedColumns, getCellWidths } = context;
         if (getVirtualizedListRef) {
             if (props.virtualized) {
                 getVirtualizedListRef(this.listRef);
@@ -152,6 +156,8 @@ class Body extends BaseComponent<BodyProps, BodyState> {
             }
         }
         this.foundation = new BodyFoundation(this.adapter);
+        this.flattenedColumns = flattenedColumns;
+        this.cellWidths = getCellWidths(flattenedColumns);
         this.observer = null;
     }
 
@@ -199,7 +205,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
                     this.observer.unobserve(bodyWrapDOM);
                     this.observer = null;
                 }
-            }
+            },
         };
     }
 
@@ -494,7 +500,12 @@ class Body extends BaseComponent<BodyProps, BodyState> {
         }
 
         const { flattenedColumns, getCellWidths } = this.context;
-        const cellWidths = getCellWidths(flattenedColumns);
+
+        // we use memoized cellWidths to avoid re-render expanded row (fix #686)
+        if (flattenedColumns !== this.flattenedColumns) {
+            this.flattenedColumns = flattenedColumns;
+            this.cellWidths = getCellWidths(flattenedColumns);
+        }
 
         return (
             <ExpandedRow
@@ -508,7 +519,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
                 index={index}
                 virtualized={virtualized}
                 key={genExpandedRowKey(key)}
-                cellWidths={cellWidths}
+                cellWidths={this.cellWidths}
             />
         );
     };

+ 18 - 0
packages/semi-ui/table/__test__/table.test.js

@@ -1930,4 +1930,22 @@ describe(`Table`, () => {
         expect(newExpandedRows.length).toEqual(1);
         expect(table.state(`expandedRowKeys`)).toEqual(['1']);
     });
+
+    it(`test expanded row re-render`, () => {
+        const expandedRowRender = sinon.spy(() => <div>Semi Design</div>);
+        const demo = mount(
+            <Table
+                columns={columns}
+                dataSource={data}
+                expandedRowRender={expandedRowRender}
+            />
+        );
+
+        const table = demo.find(BaseTable);
+
+        const expandIcons = demo.find(`.semi-table-tbody .semi-table-row .semi-table-expand-icon`);
+        expandIcons.at(0).simulate('click');
+        expandIcons.at(1).simulate('click');
+        expect(expandedRowRender.calledTwice).toBeTruthy();
+    });
 });

+ 95 - 0
packages/semi-ui/table/_story/v2/FixedExpandedRow/index.jsx

@@ -0,0 +1,95 @@
+import React from 'react';
+import { Table, Avatar } from '@douyinfe/semi-ui';
+import { IconMore } from '@douyinfe/semi-icons';
+
+const columns = [
+    {
+        title: '标题',
+        width: 500,
+        dataIndex: 'name',
+        render: (text, record, index) => {
+            return (
+                <span>
+                    <Avatar size="small" shape="square" src={record.nameIconSrc} style={{ marginRight: 12 }}></Avatar>
+                    {text}
+                </span>
+            );
+        },
+    },
+    {
+        title: '大小',
+        dataIndex: 'size',
+    },
+    {
+        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',
+    },
+    {
+        title: '',
+        dataIndex: 'operate',
+        render: () => {
+            return <IconMore />;
+        },
+    },
+];
+
+const data = [
+    {
+        key: '1',
+        name: 'Semi Design 设计稿.fig',
+        nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+        size: '2M',
+        owner: '姜鹏志',
+        updateTime: '2020-02-02 05:13',
+        avatarBg: 'grey',
+    },
+    {
+        key: '2',
+        name: 'Semi Design 分享演示文稿',
+        nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+        size: '2M',
+        owner: '郝宣',
+        updateTime: '2020-01-17 05:31',
+        avatarBg: 'red',
+    },
+    {
+        key: '3',
+        name: '设计文档',
+        nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+        size: '34KB',
+        owner: 'Zoey Edwards',
+        updateTime: '2020-01-26 11:01',
+        avatarBg: 'light-blue',
+    },
+];
+
+export default function App() {
+    const expandRowRender = (record, index) => {
+        console.log('render', index);
+        return <div>semi design</div>;
+    };
+
+    return (
+        <Table
+            rowKey="name"
+            columns={columns}
+            dataSource={data}
+            expandedRowRender={expandRowRender}
+            pagination={false}
+        />
+    );
+}

+ 2 - 1
packages/semi-ui/table/_story/v2/index.js

@@ -2,4 +2,5 @@ export { default as DefaultFilteredValue } from './defaultFilteredValue';
 export { default as FixedColumnsChange } from './FixedColumnsChange';
 export { default as FixedZIndex } from './FixedZIndex';
 export { default as FixedHeaderMerge } from './FixedHeaderMerge';
-export { default as FixedResizable } from './FixedResizable';
+export { default as FixedResizable } from './FixedResizable';
+export { default as FixedExpandedRow } from './FixedExpandedRow';