antd table合并行的columns配置动态修改列名导致的引用问题

需求背景

我需要实现一个如下的多个相邻行合并为一行的功能,之后又接到需求,要求当用户切换冗余场景时,替换Table中的某一列的名称,具体如下截图所示
在这里插入图片描述
在这里插入图片描述

踩坑

我想到的办法是,当切换冗余场景时,将Table的columns进行序列化替换文本,于是写了以下代码:

let cols = JSON.parse(JSON.stringify(columns).replace(/:"总存储量"/g, ':"存储量"'));
setColumns(cols)

接着,setColumns成功,组件重新渲染,发现合并行失效了,文本替换也没有实时更新,变成和我的判断逻辑(汇总统计=总存储量,其他统计子类=存储量)相反了。

分析,为什么会如此

分两个原因描述

1、合并行为什么失效了?

因为antd的Table组件的columns是在初始化配置的时候一次性绑定的一个引用配置,因此,后续必须使用同一个引用配置columns才能使合并行效果生效,而我使用了序列化字符串再转回js对象,这个过程产生了新的引用,导致合并行的一些效果对应不上原先的配置,因此合并行效果失效

2、文本替换为什么没有即时生效,而是走了相反的判断逻辑结果?

如果我们没有使用setState去更新columns配置,就会组件不重新render,导致UI不能及时获取到最新的值,因此会产生我们拿到的值是上一次的值的情况

正确的做法

使用splice对原引用配置columns进行替换:

useEffect(() => {
    if (isEqualRedd) {
      columns.splice(7, 1, {
        title: '总存储量',
        dataIndex: 'sumStorgCap',
        render: (text) => {
          return text + 'T';
        },
        onCell: (_, index) => {
          return {
            rowSpan: _[`${'id'}RowSpan`],
          };
        },
      });
      _setColumns(columns);
    } else {
      columns.splice(7, 1, {
        title: '存储量',
        dataIndex: 'storgCap',
        render: (text) => {
          return text + 'G';
        },
      });
      _setColumns(columns);
    }
  }, [navType, isEqualRedd]);

完整Table组件代码

import { Empty, Table } from 'antd';
import React, { useEffect, useState } from 'react';
import styles from './MergeCellTable.less';

const MergeCellTable = (props) => {
  const { navType, pagination, onPageChange, isEqualRedd } = props;
  const [data, setData] = useState([]);
  const [_columns, _setColumns] = useState([]);

  let columns = [
    {
      title: 'key',
      dataIndex: 'key',
      className: styles.notShowCol,
    },
    {
      title: '编号',
      dataIndex: 'id',
      onCell: (_, index) => {
        return {
          rowSpan: _[`${'id'}RowSpan`],
        };
      },
    },
    {
      title: '治理优先级',
      dataIndex: 'govPrior',
      onCell: (_, index) => {
        return {
          rowSpan: _[`${'id'}RowSpan`],
        };
      },
    },
    {
      title: '资产名',
      dataIndex: 'astNm',
    },
    {
      title: '所属中心',
      dataIndex: 'blngCtr',
    },
    {
      title: '责任人',
      dataIndex: 'princ',
    },
    {
      title: '冗余场景',
      dataIndex: 'redundSmlClass',
    },
    {
      title: '总存储量',
      dataIndex: 'sumStorgCap',
      render: (text) => {
        return text + 'T';
      },
      onCell: (_, index) => {
        return {
          rowSpan: _[`${'id'}RowSpan`],
        };
      },
    },
    {
      title: '冗余类型',
      dataIndex: 'redundType',
      onCell: (_, index) => {
        return {
          rowSpan: _[`${'id'}RowSpan`],
        };
      },
    },
  ];

  useEffect(() => {
    setData(props.dataSet);
  }, [props.dataSet]);

  useEffect(() => {
    if (navType === '其他') {
      columns.splice(4, 1, {
        title: '所属团队',
        dataIndex: 'blngCtr',
      });
    } else {
      columns.splice(4, 1, {
        title: '所属中心',
        dataIndex: 'blngCtr',
      });
    }
    _setColumns(columns);
  }, [navType, isEqualRedd]);

  useEffect(() => {
    if (isEqualRedd) {
      columns.splice(7, 1, {
        title: '总存储量',
        dataIndex: 'sumStorgCap',
        render: (text) => {
          return text + 'T';
        },
        onCell: (_, index) => {
          return {
            rowSpan: _[`${'id'}RowSpan`],
          };
        },
      });
      _setColumns(columns);
    } else {
      columns.splice(7, 1, {
        title: '存储量',
        dataIndex: 'storgCap',
        render: (text) => {
          return text + 'G';
        },
      });
      _setColumns(columns);
    }
  }, [navType, isEqualRedd]);

  const onChange = (page) => {
    onPageChange && onPageChange(page);
  };

  return (
    <Table
      columns={_columns}
      dataSource={data}
      bordered
      pagination={false}
      rowClassName={(record, index) => (index % 2 === 1 ? 'even' : 'odd')}
      onChange={onChange}
      locale={{
        emptyText: (
          <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无数据" />
        ),
      }}
    />
  );
};

export default MergeCellTable;

版权声明:本文为hzxOnlineOk原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。