基于 Ant Design Pro 实现表格分页与筛选参数的持久化

在开发管理系统时,表格是非常常见的 UI 组件,通常需要支持分页、筛选等功能。然而,用户在操作表格时,如新增、修改导致切换页面,返回表格页面时,如何保留之前的筛选条件和分页信息呢?本篇文章将通过一个简单的示例,教你如何使用 useTableState 自定义 Hook 来解决这一问题。

实现思路

我们需要自定义一个 hooks : useTableState 来实现操作表格与持久化参数的联系。useTableState 中通过 sessionStorage 来持久化表格的分页状态和筛选条件。

sessionStorage 是一种简单的浏览器存储方式,在页面会话期间有效,可以在页面刷新或者切换时保持数据状态,但关闭浏览器后数据会丢失。通过这个方法,我们能够让用户返回表格时,自动恢复之前的分页和筛选状态。

当然如果你觉得,希望让用户下次打开网页时,参数也能被记住,那也可以考虑用 localstorage 替换掉 sessionStorage

useTableState 代码及解析

首先,我们看一下 useTableState 自定义 Hook 的实现:

typescript 复制代码
import { useState } from "react";
​
interface TableState {
  pagination: {
    pageSize: number;
    current: number;
    total?: number;
  };
  searchParams: any;
}
​
const useTableState = (tableName: string) => {
  const storedPagination = sessionStorage.getItem(`${tableName}_pagination`);
  const storedSearchParams = sessionStorage.getItem(`${tableName}_searchParams`);
  const [pagination, setPagination] = useState<TableState["pagination"]>(
    !!storedPagination
      ? JSON.parse(storedPagination)
      : {
          pageSize: 10,
          current: 1,
        }
  );
  const [searchParams, setSearchParams] = useState(!!storedSearchParams ? JSON.parse(storedSearchParams) : {});
​
  const handleTableChange = (pagination: any, filters: any) => {
    // 存储筛选项和页码到 sessionStorage
    sessionStorage.setItem(`${tableName}_pagination`, JSON.stringify(pagination));
    sessionStorage.setItem(`${tableName}_searchParams`, JSON.stringify(filters));
    setPagination(pagination);
    setSearchParams(filters);
  };
​
  return {
    pagination,
    searchParams,
    handleTableChange,
  };
};
​
export default useTableState;

在这段代码中,useTableState Hook 做了以下几件事:

  1. 读取存储数据 :从 sessionStorage 中获取之前保存的分页和筛选条件,如果存在则使用这些值,若没有则使用默认值。
  2. 状态管理 :使用 useState 保存分页和筛选条件的状态。
  3. 更新状态 :通过 handleTableChange 函数更新分页和筛选条件,同时将新状态保存到 sessionStorage 中,确保用户返回时能够恢复之前的操作。

如何在表格页面使用这个 Hook

接下来,我们在表格页面中如何使用这个 useTableState 来实现状态持久化。以下是一个基于 Ant Design Pro 的表格页面示例:

typescript 复制代码
const columns: ProColumns<TExamPart>[] = [
  {
    title: "姓名",
    dataIndex: "name",
  },
  {
    title: "年龄",
    dataIndex: "age",
  }
];
​
const UserManagement = () => {
  const ref = useRef<ActionType>();
  
  /************ 关键代码开始 ************/
  const formRef = useRef<ProFormInstance>();
  /************ 关键代码结束 ************/
  
  const [showModifyModal, setModifyModal] = useState<boolean | string>(false);
  const [showDeleteModal, setShowDeleteModal] = useState<false | string>(false);
  
  /************ 关键代码开始 ************/
  const { pagination, searchParams, handleTableChange } = useTableState("guideManager");
​
  useEffect(() => {
    formRef.current?.setFieldsValue({
      ...searchParams,
    });
  }, []);
  /************ 关键代码结束 ************/
​
  return (
    <PageContainer breadcrumb={undefined}>
      <ProTable
        actionRef={ref}
        
        /************ 关键代码开始 ************/
        formRef={formRef}
        /************ 关键代码结束 ************/
        
        toolBarRender={() => [
          <Button key="add-btn" type="primary" onClick={() => setModifyModal(true)}>
            新增
          </Button>,
        ]}
        rowKey="id"
        columns={[
          ...columns,
          {
            title: "操作",
            search: false,
            render: (_index, { id }) => {
              return (
                <Space>
                  <a
                    onClick={() => {
                      setModifyModal(id);
                    }}
                  >
                    修改用户
                  </a>
                  <a
                    onClick={() => {
                      setShowDeleteModal(id);
                    }}
                  >
                    删除
                  </a>
                </Space>
              );
            },
          },
        ]}
        
        /************ 关键代码开始 ************/
        request={(values) => {
          return request<{
            data: TUser[];
          }>("/api/xxx/list", {
            method: "GET",
            params: {
              ...values,
            },
          }).then((res) => {
            const { current, pageSize, ...rest } = values;
​
            handleTableChange(
              {
                current,
                pageSize,
                total: res.data.length,
              },
              {
                ...searchParams,
                ...rest,
              }
            );
​
            return {
              data: res.data,
              success: true,
            };
          });
        }}
        onChange={(pagination, filters) => {
          handleTableChange(pagination, { ...searchParams, ...filters });
        }}
        pagination={{
          ...pagination,
        }}
        /************ 关键代码结束 ************/
        
      />
      <ModifyModal
        showModal={showModifyModal}
        handleCancel={() => setModifyModal(false)}
        handleOk={() => {
          ref.current?.reload();
          setModifyModal(false);
        }}
      />
      <DeleteModal
        title="删除用户"
        content="确定要删除该用户吗?"
        showModal={!!showDeleteModal}
        handleCancel={() => setShowDeleteModal(false)}
        handleOk={() => {
          if (showDeleteModal) {
            request<{ data: boolean }>("/api/xxx/delete", {
              method: "DELETE",
              data: {
                id: showDeleteModal,
              },
            }).then(({ data }) => {
              if (data) {
                message.success("删除成功!");
                ref.current?.reload();
                setShowDeleteModal(false);
              }
            });
          }
        }}
      />
    </PageContainer>
  );
};
​
export default UserManagement;
  • formRef 用于绑定表单,以便在加载时能够填充表单字段
  • useTableState 用于管理分页和筛选条件,它会通过 sessionStorage 持久化表格的状态。
  • useEffect 空依赖用于在组件加载时,设置表单的默认值(即筛选条件)。`
  • request 方法会根据分页和筛选条件从后端获取用户数据,并在数据返回后,更新表格的分页和筛选条件。
  • onChange 方法更新页码参数(因为后端没有做分页)
  • pagination 属性改为受控的

总结

通过以上操作,就可以轻松实现了表格分页和筛选状态的持久化,使得用户在返回表格时能够自动恢复之前的操作状态,希望可以对阅读文章的你有帮助!

相关推荐
NoneCoder1 小时前
JavaScript系列(87)--Webpack 高级配置详解
前端·javascript·webpack
fengfeng N3 小时前
AxiosError: Network Error
前端·https·axios·跨域换源
StarPlatinum24 小时前
CSS实现一张简易的贺卡
前端·css
Stestack4 小时前
Python 给 Excel 写入数据的四种方法
前端·python·excel
SRC_BLUE_174 小时前
[Web 安全] PHP 反序列化漏洞 —— PHP 序列化 & 反序列化
前端·安全·web安全·php
石兴稳4 小时前
SSD 固态硬盘存储密度的分区
开发语言·javascript·数据库
念九_ysl4 小时前
前端排序算法完全指南:从理论到实践
开发语言·javascript·算法·ecmascript
IT猿手4 小时前
智能优化算法:雪橇犬优化算法(Sled Dog Optimizer,SDO)求解23个经典函数测试集,MATLAB
开发语言·前端·人工智能·算法·机器学习·matlab
懒人村杂货铺5 小时前
父子组件事件冒泡和捕获的顺序
前端·javascript·react.js