前言
最近在重构 Open-Job 的前端项目时发现,项目中有多处用到了 Antd 的 table 组件,而且都还是分页的,这些分页请求的逻辑还都差不多,只有请求的接口不一样,所以就会产生很多重复的代码,例如下面这样
重复代码块
const TableList: React.FC = () => {
const [loading, setLoading] = useState(false);
const [tableData, setTableData] = useState([]);
const [tableParams, setTableParams] = useState<TableParams>({
pagination: {
current: 1,
pageSize: 10,
},
});
const fetchData = async () => {
setLoading(true);
try {
const response: any = await fetchDataPage({
current: tableParams.pagination?.current,
pageSize: tableParams.pagination?.pageSize,
});
setTableData(response?.records);
setTableParams({
...tableParams,
pagination: {
...tableParams.pagination,
total: response.total,
},
});
} catch (error) {
message.error('服务繁忙,请稍后重试');
} finally {
setLoading(false);
}
};
}
上面提到的 TableParams
结构如下,其中 fetchDataPage
就是我们请求的后端分页接口。
export interface TableParams {
pagination?: TablePaginationConfig;
order?: any;
filters?: Record<string, FilterValue>;
}
那如果我们有多个这样的操作,就会产生很多重复的代码,其中只有后端接口是不一样的,那接下来我们就来优化下.
定义分页请求钩子函数
这里,我定义了一个分页请求钩子函数,源码在最后
import { useEffect, useState } from 'react';
import { message, TablePaginationConfig } from 'antd';
import { PageQuery, PageResult } from '@/lib/request';
import { TableParams } from '@/types/typings';
/**
* antd table 分页请求钩子函数
*
* <p>
* @param request 你的数据请求 api
* @return [
* data:table 数据,
* loading: 加载状态,
* tableParams:分页参数,
* onTableChange:切换分页事件,
* fetchData:方便外部主动触发数据加载
* ]
* </p>
*
*/
const usePaginationRequest = <T>(
request: (params: PageQuery) => Promise<PageResult<T>>
): [
T[],
boolean,
TableParams,
(pagination: TablePaginationConfig) => void,
() => Promise<void>,
] => {
const [data, setData] = useState<T[]>([]);
const [loading, setLoading] = useState(false);
const [tableParams, setTableParams] = useState<TableParams>({
pagination: {
current: 1,
pageSize: 10,
},
});
const fetchData = async () => {
setLoading(true);
try {
const response: PageResult<T> = await request({
current: tableParams.pagination?.current,
pageSize: tableParams.pagination?.pageSize,
});
setData(response?.records);
setTableParams({
...tableParams,
pagination: {
...tableParams.pagination,
total: response.total,
},
});
} catch (error) {
message.error('服务繁忙,请稍后重试');
} finally {
setLoading(false);
}
};
const onTableChange = (pagination: TablePaginationConfig) => {
setTableParams({
pagination,
});
// `dataSource` is useless since `pageSize` changed
if (pagination.pageSize !== tableParams.pagination?.pageSize) {
setData([]);
}
};
useEffect(() => {
fetchData().then();
}, [JSON.stringify(tableParams)]);
return [data, loading, tableParams, onTableChange, fetchData];
};
export default usePaginationRequest;
使用分页请求钩子函数
const JobTableList: React.FC = () => {
const request = async (params: PageParams) => {
return await fetchDataPage({
current: params.current,
pageSize: params.pageSize,
});
};
const [tableData, loading, tableParams, onTableChange, fetchData] =
usePaginationRequest<OpenJob>((params) => request(params));
}
这样代码是不是少了很多,这样我们在其他地方就只需要像上面这样写少量的代码就可以实现分页请求了,是不是很爽。
这时,如果你需要在请求时添加其他参数,那就可以像下面这样处理啦,非常的简单。
const JobTableList: React.FC = () => {
const [form] = Form.useForm();
const request = async (params: PageParams) => {
const values = form.getFieldsValue();
return await fetchDataPage({
...values,
current: params.current,
pageSize: params.pageSize,
});
};
const [tableData, loading, tableParams, onTableChange, fetchData] =
usePaginationRequest<OpenJob>((params) => request(params));
}
项目地址: github.com/lijunping36…
感谢老铁的三连🤞