基于 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 属性改为受控的

总结

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

相关推荐
庸俗今天不摸鱼20 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX1873021 分钟前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下27 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox37 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞40 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行40 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581041 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周1 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
Jasmin Tin Wei2 小时前
蓝桥杯 web 学海无涯(axios、ecahrts)版本二
前端·蓝桥杯