AntD Table组件selectedRows翻页后保留上一页已选中items项

问题描述

用户在翻页后丢失已选中的数据,只能在已分页的数据中进行修改操作,尤其是在填写分步表单时,上一步及下一步也会丢失数据

主要API

  1. Ant Design
    onSelect: 用户手动选择/取消选择某行的回调
    onSelectAll: 用户手动选择/取消选择所有行的回调
    不使用 onSelectChange,原因为:当指定selectedRowKeys(需要被选中的id集合),会在表格渲染时重复setState,致使selectedRowKeys值丢失,无法保留选中状态
    具体可参考: https://ant.design/components/table-cn/#rowSelection
  2. Lodash
    _.remove: 移除数组中predicate(断言)返回为真值的所有元素
    _.map: 遍历 collection(集合)中的每个元素后返回的结果,此处主要用来获取指定键的值数组
    _.concat:合并两个数组或集合
    _.uniqBy: 根据指定键比较进行去重
    _.includes:判断数组是否包含某个元素
    具体可参考: https://www.lodashjs.com/docs/latest

解决思路

起初想通过state去控制selectedRowKeys(选中项),但是由于分布填写表单的原因,在切换时会丢失state,因此采用Props控制选中项使其成为完全受控组件。
然后通过onSelect和onSelectAll控制用户手动触发选中项更改props值,而非onSelectChange只监控选中与否,避免选中项丢失的问题。

具体解决方法

  • 数据层(models)
// 定义数据格式
export interface StateType {
  selectedRowKeys?: any[];
  selectedRows?: any[];
}
// 定义models格式
export interface ModelType {
  namespace: string;
  state: StateType;
  effects: {};
  reducers: {
    saveSelectedRowKeys: Reducer<StateType>;
  };
}
const Model: ModelType = {
  namespace: 'formAndstepForm',
  state: {
    selectedRowKeys: [],
    selectedRows: [],
  },

  effects: {},

  reducers: {
    saveSelectedRowKeys(state, { payload }) {
      return {
        ...state,
        ...payload,
      };
    },
  },
};

export default Model;
  • 页面层(pages)
import React from 'react';
import ProTable, { ProColumns } from '@ant-design/pro-table';
import _ from 'lodash';
interface Step2Props extends Partial<ConnectProps> {
  selectedRowKeys: any;
  selectedRows: any;
}
interface Step2States {}
class Step2 extends React.Component<Step2Props, Step2States> {
	/**
   * @name: 手动选中复选框
   * @msg: 
   * @param {type} 
   * @return: 
   */
  onSelect = (record: any, selected: any) => {
    const mySelectedRows = this.props.selectedRows;
    const { dispatch } = this.props;
    if(selected){
      mySelectedRows.push(record);
    }else{
      _.remove(mySelectedRows, (o: any) => {return o.deviceId === record.deviceId});
    }
    const selectedRowKeys =  _.map(mySelectedRows,'id');
    if(dispatch){
      dispatch({
        type: 'formAndstepForm/saveSelectedRowKeys',
        payload: {
          selectedRowKeys,
          selectedRows: mySelectedRows,
        },
      });
    }
  }

  onSelectAll = (selected: any, selectedRows: any, changeRows: any) => {
    let mySelectedRows = this.props.selectedRows;
    const changeRowKeys =  _.map(changeRows,'id');
    const { dispatch } = this.props;
    if(selected){
      // 先连接再进行一次去重
      mySelectedRows = _.uniqBy(_.concat(mySelectedRows,changeRows), 'id');
    }else{
      // 先判断包含再移除
      _.remove(mySelectedRows, (o: any) => {return _.includes(changeRowKeys,o.deviceId)});
    }
    const selectedRowKeys =  _.map(mySelectedRows,'id');
    if(dispatch){
      dispatch({
        type: 'formAndstepForm/saveSelectedRowKeys',
        payload: {
          selectedRowKeys,
          selectedRows: mySelectedRows,
        },
      });
    }
  }
  render() {
    const {
      opcFilterTab,
      loading,
      paginationFilter,
      selectedRowKeys,
    } = this.props;

    const columns: ProColumns<OpcFilterInfo>[] = [
      
    ];

    const rowSelection = {
      selectedRowKeys,
      onSelect: this.onSelect,
      onSelectAll: this.onSelectAll,
    };

    return (
      <>
          <ProTable
            rowKey={(record) => record.id}
            loading={loading}
            columns={columns}
            dataSource={opcFilterTab}
            search={false}
            toolBarRender={false}
            rowSelection={rowSelection}
            options={false}
            tableAlertRender={false}
            pagination={{
              ...paginationFilter,
              showQuickJumper: true,
              showSizeChanger: true,
              showTotal: () =>
                `${paginationFilter ? paginationFilter.current : 0}/${
                  paginationFilter ? paginationFilter.totalPages : 0
                }`,
            }}
          />
      </>
    );
  }
}
export default connect(
  ({
    formAndstepForm,
  }: {
    formAndstepForm: StateType;
  }) => ({
    selectedRowKeys: formAndstepForm.selectedRowKeys,
    selectedRows: formAndstepForm.selectedRows,
    opcFilterTab: opc.opcFilterTab,
    paginationFilter: opc.paginationFilter,
  }),
)(Step2);

注意事项

针对数据处理可使用lodash使得代码整洁,可参考api理解使用,同时注意数据排序,避免选中项位置改变

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐