AntD 表格组件rowSelection翻页后保留上一页已选中项

1,758 阅读2分钟

遇到的问题

  • 翻页后数据丢失
  • 用户选中取消选中, 全选, 取消全选操作无法通过一个函数解决(优雅的解决)
  • 无法简单的通过rowSelectiononChangeAPI进行保留数据操作
  • 用户在第一页点击全选后点击下一页,在回到第一页,选中状态需要保留

情景描述

  • 项目架构:dva + umi + lodash
  • 每次改变分页都会重新请求数据

解决方法

  • 通过rowSelectiononSelect方法和onSelectAll 来判断是否是全选
  • 根据参数selected来判断用户操作

代码实现

  • dipatch的写法不明白的可以看我上一篇文章
  • 简化后的代码,只保留了主要部分,cv无法运行
import React from 'react';
import {Table} from 'antd';
import _ from 'lodash';
import {connect} from 'dva';
import type {AllModels, DvaDispatch} from "@/type";
import type {TablePaginationConfig} from 'antd';
import type {GroupingClassModel, AddStudentTableItem} from "@/pages/GroupingClass/models";

const ModalTable: React.FC<{
  dispatch: DvaDispatch
  selectedStudent: AddStudentTableItem[]
  selectedStudentKey: React.Key[]
}> = ({
        dispatch,
        selectedStudent,
        selectedStudentKey
      }) => {

  /**
   * @function 表格的item被选中或者取消选中
   * @param {AddStudentTableItem} record - 被操作的数据
   * @param {boolean} selected - true:选中;false:取消选中
   * @description <br>
   *  - 如果是 选中 操作: 直接往 存在model里的已被选中的数组 里添加即可
   *  - 如果是 删除 操作: 在 存在model里的已被选中的数组 里删除对应的元素(根据table的key值做判断)
   *  - 根据最新的 被选中的数组 生成最新的选中的key值数组(用以回显状态)
   *  - 通过dispatch函数进行更新
   */
  function tableItemOnSelect(record: AddStudentTableItem, selected: boolean) {
    const newSelectedRows = _.cloneDeep(selectedStudent);
    if (selected) newSelectedRows.push(record);
    if (!selected) _.remove(newSelectedRows, (item: AddStudentTableItem) => item.studentId === record.studentId);
    const selectedRowKeys = _.map(newSelectedRows,'studentId');
    dispatch<GroupingClassModel>({
      type: 'groupingClassModel/updateState',
      payload: {
        selectedStudent: newSelectedRows,
        selectedStudentKey: selectedRowKeys
      }
    })
  }

  /**
   * @function 当前表格被 全选 或 取消全选
   * @param {boolean} selected - true:全选;false:取消全选
   * @param {AddStudentTableItem[]} selectedRows - 被选中的数据(用不到)
   * @param {AddStudentTableItem[]} changeRows - 被改变选中状态的数据
   * @description <br>
   *  - 如果是 全选 操作: 拼接 存在model里的已被选中的数组 和 被改变选中状态的数组, 然后通过studentId(table的key值)去重
   *  - 如果是 取消全选 操作: 在 存在model里的已被选中的数组 删除 studentId(table的key值)一样的元素
   *  - 根据最新的 被选中的数组 生成最新的选中的key值数组(用以回显状态)
   *  - 通过dispatch函数进行更新
   */
  function tableOnSelectAll(selected: boolean, selectedRows: AddStudentTableItem[], changeRows: AddStudentTableItem[]) {
    let newSelectedRows = _.cloneDeep(selectedStudent);
    const changeRowKeys =  _.map(changeRows,'studentId');
    if (selected) newSelectedRows = _.uniqBy(_.concat(newSelectedRows,changeRows), 'studentId');
    if (!selected) _.remove(newSelectedRows, (item: AddStudentTableItem) => _.includes(changeRowKeys, item.studentId));
    const selectedRowKeys = _.map(newSelectedRows,'studentId');
    dispatch<GroupingClassModel>({
      type: 'groupingClassModel/updateState',
      payload: {
        selectedStudent: newSelectedRows,
        selectedStudentKey: selectedRowKeys
      }
    })
  }

  return (
    <Table
      rowSelection={{
        type: 'checkbox',
        onSelect: tableItemOnSelect,
        onSelectAll: tableOnSelectAll,
        selectedRowKeys: selectedStudentKey
      }}
    />
  )
}

const mapStateToProps = (state: AllModels) => {
  return {
    selectedStudent: state.groupingClassModel.selectedStudent,
    selectedStudentKey: state.groupingClassModel.selectedStudentKey,
  }
}
export default connect(mapStateToProps)(ModalTable)