Skip to content

Commit cce04cb

Browse files
committed
refactor(table): enhance useTable hook by simplifying configuration and improving pagination handling. close #65
1 parent cc7238a commit cce04cb

File tree

3 files changed

+153
-133
lines changed

3 files changed

+153
-133
lines changed

src/features/table/use-table.ts

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,32 @@ import { getIsMobile } from '@/layouts/appStore';
77

88
type TableData = AntDesign.TableData;
99
type GetTableData<A extends AntDesign.TableApiFn> = AntDesign.GetTableData<A>;
10+
1011
type TableColumn<T> = AntDesign.TableColumn<T>;
11-
type Config<A extends AntDesign.TableApiFn> = AntDesign.AntDesignTableConfig<A> & {
12-
isChangeURL?: boolean;
12+
13+
type Config<A extends AntDesign.TableApiFn> = AntDesign.AntDesignTableConfig<A>;
14+
15+
type CustomTableProps<A extends AntDesign.TableApiFn> = Omit<
16+
TableProps<AntDesign.TableDataWithIndex<GetTableData<A>>>,
17+
'loading'
18+
> & {
19+
loading: boolean;
1320
};
1421

15-
export function useTable<A extends AntDesign.TableApiFn>(
16-
config: Config<A>,
17-
paginationConfig?: Omit<TablePaginationConfig, 'current' | 'onChange' | 'pageSize' | 'total'>
18-
) {
22+
export function useTable<A extends AntDesign.TableApiFn>(config: Config<A>) {
1923
const isMobile = useAppSelector(getIsMobile);
2024

21-
const { apiFn, apiParams, immediate, isChangeURL = true, rowKey = 'id' } = config;
25+
const {
26+
apiFn,
27+
apiParams,
28+
columns: columnsFactory,
29+
immediate,
30+
isChangeURL = true,
31+
onChange: onChangeCallback,
32+
pagination: paginationConfig,
33+
rowKey = 'id',
34+
...rest
35+
} = config;
2236

2337
const [form] = Form.useForm<AntDesign.AntDesignTableConfig<A>['apiParams']>();
2438

@@ -42,7 +56,7 @@ export function useTable<A extends AntDesign.TableApiFn>(
4256
} = useHookTable<A, GetTableData<A>, TableColumn<AntDesign.TableDataWithIndex<GetTableData<A>>>>({
4357
apiFn,
4458
apiParams: { ...apiParams, ...query },
45-
columns: config.columns,
59+
columns: columnsFactory,
4660
getColumnChecks: cols => {
4761
const checks: AntDesign.TableColumnCheck[] = [];
4862

@@ -95,12 +109,6 @@ export function useTable<A extends AntDesign.TableApiFn>(
95109
// this is for mobile, if the system does not support mobile, you can use `pagination` directly
96110
const pagination: TablePaginationConfig = {
97111
current: pageNum,
98-
onChange: async (current: number, size: number) => {
99-
updateSearchParams({
100-
current,
101-
size
102-
});
103-
},
104112
pageSize,
105113
pageSizeOptions: ['10', '15', '20', '25', '30'],
106114
showSizeChanger: true,
@@ -119,14 +127,21 @@ export function useTable<A extends AntDesign.TableApiFn>(
119127

120128
if (res) {
121129
if (isResetCurrent) {
122-
const { current = 1, ...rest } = res;
123-
updateSearchParams({ current, ...rest });
130+
const { current = 1, ...other } = res;
131+
updateSearchParams({ current, ...other });
124132
} else {
125133
updateSearchParams(res);
126134
}
127135
}
128136
}
129137

138+
function handleChange(paginationContext: TablePaginationConfig) {
139+
updateSearchParams({
140+
current: paginationContext.current,
141+
size: paginationContext.pageSize
142+
});
143+
}
144+
130145
return {
131146
columnChecks,
132147
data,
@@ -144,9 +159,11 @@ export function useTable<A extends AntDesign.TableApiFn>(
144159
columns,
145160
dataSource: data,
146161
loading,
162+
onChange: onChangeCallback ?? handleChange,
147163
pagination,
148-
rowKey
149-
}
164+
rowKey,
165+
...rest
166+
} as CustomTableProps<A>
150167
};
151168
}
152169

src/pages/(base)/manage/user/index.tsx

Lines changed: 113 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -23,126 +23,126 @@ const UserManage = () => {
2323

2424
const isMobile = useMobile();
2525

26-
const { columnChecks, data, run, searchProps, setColumnChecks, tableProps } = useTable(
27-
{
28-
apiFn: fetchGetUserList,
29-
apiParams: {
30-
current: 1,
31-
nickName: null,
32-
size: 10,
33-
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
34-
// the value can not be undefined, otherwise the property in Form will not be reactive
35-
status: null,
36-
userEmail: null,
37-
userGender: null,
38-
userName: null,
39-
userPhone: null
26+
const { columnChecks, data, run, searchProps, setColumnChecks, tableProps } = useTable({
27+
apiFn: fetchGetUserList,
28+
apiParams: {
29+
current: 1,
30+
nickName: null,
31+
size: 10,
32+
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
33+
// the value can not be undefined, otherwise the property in Form will not be reactive
34+
status: null,
35+
userEmail: null,
36+
userGender: null,
37+
userName: null,
38+
userPhone: null
39+
},
40+
columns: () => [
41+
{
42+
align: 'center',
43+
dataIndex: 'index',
44+
key: 'index',
45+
title: t('common.index'),
46+
width: 64
4047
},
41-
columns: () => [
42-
{
43-
align: 'center',
44-
dataIndex: 'index',
45-
key: 'index',
46-
title: t('common.index'),
47-
width: 64
48-
},
49-
{
50-
align: 'center',
51-
dataIndex: 'userName',
52-
key: 'userName',
53-
minWidth: 100,
54-
title: t('page.manage.user.userName')
55-
},
56-
{
57-
align: 'center',
58-
dataIndex: 'userGender',
59-
key: 'userGender',
60-
render: (_, record) => {
61-
if (record?.userGender === null) {
62-
return null;
63-
}
64-
65-
const label = t(userGenderRecord[record.userGender]);
66-
67-
return <ATag color={tagUserGenderMap[record.userGender]}>{label}</ATag>;
68-
},
69-
title: t('page.manage.user.userGender'),
70-
width: 100
71-
},
72-
{
73-
align: 'center',
74-
dataIndex: 'nickName',
75-
key: 'nickName',
76-
minWidth: 100,
77-
title: t('page.manage.user.nickName')
78-
},
79-
{
80-
align: 'center',
81-
dataIndex: 'userPhone',
82-
key: 'userPhone',
83-
title: t('page.manage.user.userPhone'),
84-
width: 120
85-
},
86-
{
87-
align: 'center',
88-
dataIndex: 'userEmail',
89-
key: 'userEmail',
90-
minWidth: 200,
91-
title: t('page.manage.user.userEmail')
48+
{
49+
align: 'center',
50+
dataIndex: 'userName',
51+
key: 'userName',
52+
minWidth: 100,
53+
title: t('page.manage.user.userName')
54+
},
55+
{
56+
align: 'center',
57+
dataIndex: 'userGender',
58+
key: 'userGender',
59+
render: (_, record) => {
60+
if (record?.userGender === null) {
61+
return null;
62+
}
63+
64+
const label = t(userGenderRecord[record.userGender]);
65+
66+
return <ATag color={tagUserGenderMap[record.userGender]}>{label}</ATag>;
9267
},
93-
{
94-
align: 'center',
95-
dataIndex: 'status',
96-
key: 'status',
97-
render: (_, record) => {
98-
if (record.status === null) {
99-
return null;
100-
}
101-
const label = t(enableStatusRecord[record.status]);
102-
return <ATag color={ATG_MAP[record.status]}>{label}</ATag>;
103-
},
104-
title: t('page.manage.user.userStatus'),
105-
width: 100
68+
title: t('page.manage.user.userGender'),
69+
width: 100
70+
},
71+
{
72+
align: 'center',
73+
dataIndex: 'nickName',
74+
key: 'nickName',
75+
minWidth: 100,
76+
title: t('page.manage.user.nickName')
77+
},
78+
{
79+
align: 'center',
80+
dataIndex: 'userPhone',
81+
key: 'userPhone',
82+
title: t('page.manage.user.userPhone'),
83+
width: 120
84+
},
85+
{
86+
align: 'center',
87+
dataIndex: 'userEmail',
88+
key: 'userEmail',
89+
minWidth: 200,
90+
title: t('page.manage.user.userEmail')
91+
},
92+
{
93+
align: 'center',
94+
dataIndex: 'status',
95+
key: 'status',
96+
render: (_, record) => {
97+
if (record.status === null) {
98+
return null;
99+
}
100+
const label = t(enableStatusRecord[record.status]);
101+
return <ATag color={ATG_MAP[record.status]}>{label}</ATag>;
106102
},
107-
{
108-
align: 'center',
109-
key: 'operate',
110-
render: (_, record) => (
111-
<div className="flex-center gap-8px">
112-
<AButton
113-
ghost
114-
size="small"
115-
type="primary"
116-
onClick={() => edit(record.id)}
117-
>
118-
{t('common.edit')}
119-
</AButton>
103+
title: t('page.manage.user.userStatus'),
104+
width: 100
105+
},
106+
{
107+
align: 'center',
108+
key: 'operate',
109+
render: (_, record) => (
110+
<div className="flex-center gap-8px">
111+
<AButton
112+
ghost
113+
size="small"
114+
type="primary"
115+
onClick={() => edit(record.id)}
116+
>
117+
{t('common.edit')}
118+
</AButton>
119+
<AButton
120+
size="small"
121+
onClick={() => nav(`/manage/user/${record.id}`)}
122+
>
123+
详情
124+
</AButton>
125+
<APopconfirm
126+
title={t('common.confirmDelete')}
127+
onConfirm={() => handleDelete(record.id)}
128+
>
120129
<AButton
130+
danger
121131
size="small"
122-
onClick={() => nav(`/manage/user/${record.id}`)}
123132
>
124-
详情
133+
{t('common.delete')}
125134
</AButton>
126-
<APopconfirm
127-
title={t('common.confirmDelete')}
128-
onConfirm={() => handleDelete(record.id)}
129-
>
130-
<AButton
131-
danger
132-
size="small"
133-
>
134-
{t('common.delete')}
135-
</AButton>
136-
</APopconfirm>
137-
</div>
138-
),
139-
title: t('common.operate'),
140-
width: 195
141-
}
142-
]
143-
},
144-
{ showQuickJumper: true }
145-
);
135+
</APopconfirm>
136+
</div>
137+
),
138+
title: t('common.operate'),
139+
width: 195
140+
}
141+
],
142+
pagination: {
143+
showQuickJumper: true
144+
}
145+
});
146146

147147
const { checkedRowKeys, generalPopupOperation, handleAdd, handleEdit, onBatchDeleted, onDeleted, rowSelection } =
148148
useTableOperate(data, run, async (res, type) => {

src/types/antd.d.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ declare namespace AntDesign {
33
type TableColumnGroupType<T> = import('antd').TableColumnGroupType<T>;
44
type TablePaginationConfig = import('antd').TablePaginationConfig;
55
type TableColumnCheck = import('@sa/hooks').TableColumnCheck;
6+
type TableProps = import('antd').TableProps;
67
type TableDataWithIndex<T> = import('@sa/hooks').TableDataWithIndex<T>;
78
type FlatResponseData<T> = import('@sa/axios').FlatResponseData<T>;
89

@@ -35,6 +36,8 @@ declare namespace AntDesign {
3536

3637
type AntDesignTableConfig<A extends TableApiFn> = Pick<
3738
import('@sa/hooks').TableConfig<A, GetTableData<A>, TableColumn<TableDataWithIndex<GetTableData<A>>>>,
38-
'apiFn' | 'apiParams' | 'columns' | 'immediate'
39-
> & { rowKey?: keyof GetTableData<A> };
39+
'apiFn' | 'apiParams' | 'columns' | 'immediate' | 'isChangeURL'
40+
> & {
41+
rowKey?: keyof GetTableData<A> | ((record: GetTableData<A>) => string | number);
42+
} & Omit<TableProps, 'columns' | 'dataSource' | 'loading' | 'rowKey'>;
4043
}

0 commit comments

Comments
 (0)