Skip to content

Commit 9092737

Browse files
brickspertttys026
authored andcommitted
feature to master v1.3.0 (#107)
* feat: add useSelections * refactor: rewrite useSelections and add test * fix: fix test of useSelections * refactor: useUpdateEffect (#103) * feat: add useUpdateEffect * feat: useSelections add setSelected and add test * refactor: return object instead of array * feat: add demo for useSelections * docs: add document for useSelections * fix: fix demo of useSelections * feat: add usePagination * chore: add usePagination reference * fix: Put the function with same deps into one useMeno * feat: useAntdTable add sorter, filters * fix: deps error * fix: change halfSelected -> partiallySelected * fix: useAntdTable determine if filters are equal change to a more robust method * feat: add usePagination (#105) * feat: add usePagination
1 parent d1aeeff commit 9092737

File tree

19 files changed

+1127
-34
lines changed

19 files changed

+1127
-34
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"pub:doc": "now --prod"
3030
},
3131
"dependencies": {
32-
"react-use": "^10.6.2",
32+
"lodash.isequal": "^4.5.0",
3333
"resize-observer-polyfill": "^1.5.1"
3434
},
3535
"peerDependencies": {

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import useVirtualList from './useVirtualList';
1010
import { configResponsive, useResponsive } from './useResponsive';
1111
import useSize from './useSize';
1212
import useLocalStorageState from './useLocalStorageState';
13+
import useUpdateEffect from './useUpdateEffect';
14+
import usePagination from './usePagination';
1315

1416
const useControlledValue: typeof useControllableValue = function (...args) {
1517
console.warn(
@@ -34,4 +36,6 @@ export {
3436
useSize,
3537
configResponsive,
3638
configRequest,
39+
useUpdateEffect,
40+
usePagination,
3741
};

src/useAntdTable/SorterDemo.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Table } from 'antd';
2+
import React from 'react';
3+
import useAntdTable from '.';
4+
5+
const Demo = () => {
6+
const getTableData = ({ current, pageSize, ...rest }) => {
7+
console.log(current, pageSize, rest);
8+
return fetch(`https://randomuser.me/api?results=55&page=${current}&size=${pageSize}`)
9+
.then(res => res.json())
10+
.then(res => ({
11+
page: res.info.page,
12+
total: res.info.results,
13+
data: res.results,
14+
}));
15+
};
16+
17+
const { tableProps, filters, sorter } = useAntdTable(getTableData, [], {
18+
defaultPageSize: 5,
19+
});
20+
21+
const columns = [
22+
{
23+
title: 'name',
24+
dataIndex: 'name',
25+
key: 'name',
26+
width: 100,
27+
render(_, record) {
28+
return record.name.title;
29+
},
30+
},
31+
{
32+
title: 'email',
33+
dataIndex: 'email',
34+
key: 'email',
35+
sorter: true,
36+
sortOrder: sorter.field === 'email' && sorter.order,
37+
width: 350,
38+
},
39+
{
40+
title: 'phone',
41+
dataIndex: 'phone',
42+
key: 'phone',
43+
},
44+
{
45+
title: 'gender',
46+
key: 'gender',
47+
filters: [{ text: 'male', value: 'male' }, { text: 'female', value: 'female' }],
48+
filteredValue: filters.gender,
49+
width: 200,
50+
dataIndex: 'gender',
51+
},
52+
];
53+
54+
return <Table columns={columns} rowKey="email" {...tableProps} />;
55+
};
56+
57+
export default Demo;

src/useAntdTable/__tests__/index.test.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,40 @@ describe('useAntdTable', () => {
9797
expect(hook.result.current.tableProps.pagination.pageSize).toEqual(10);
9898
expect(hook.result.current.tableProps.pagination.total).toEqual(20);
9999
});
100-
100+
it('should sorter, filters work', async () => {
101+
queryArgs = undefined;
102+
act(() => {
103+
hook = setUp({
104+
asyncFn,
105+
});
106+
});
107+
await hook.waitForNextUpdate();
108+
act(() => {
109+
hook.result.current.tableProps.onChange({
110+
current: 2,
111+
pageSize: 5,
112+
});
113+
});
114+
await hook.waitForNextUpdate();
115+
expect(hook.result.current.tableProps.pagination.current).toEqual(2);
116+
/* 改变 filter, sorter */
117+
act(() => {
118+
hook.result.current.tableProps.onChange(
119+
{
120+
current: 2,
121+
pageSize: 5,
122+
},
123+
{ gender: ['male'] },
124+
{ field: 'email', order: 'ascend' } as any,
125+
);
126+
});
127+
await hook.waitForNextUpdate();
128+
expect(queryArgs.current).toEqual(1);
129+
expect(queryArgs.pageSize).toEqual(5);
130+
expect(queryArgs.sorter.field).toEqual('email');
131+
expect(queryArgs.sorter.order).toEqual('ascend');
132+
expect(queryArgs.filters.gender[0]).toEqual('male');
133+
});
101134
it('should form, defaultPageSize, id work', async () => {
102135
queryArgs = undefined;
103136
act(() => {

src/useAntdTable/index.mdx

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Button, Col, Form, Input, Row, Select, Table } from 'antd';
1111
import { useState } from 'react';
1212
import CacheDemo from './CacheDemo';
1313
import Demo from './Demo';
14+
import SorterDemo from './SorterDemo';
1415
import useAntdTable from './';
1516

1617
# useAntdTable
@@ -57,7 +58,7 @@ import useAntdTable from './';
5758
dataIndex: 'name',
5859
key: 'name',
5960
width: 100,
60-
render({ }, record) {
61+
render(_, record) {
6162
return record.name.title;
6263
},
6364
},
@@ -100,6 +101,15 @@ import useAntdTable from './';
100101
}
101102
</Playground>
102103

104+
### 带筛选与排序的表格
105+
106+
<Playground>
107+
<>
108+
<SorterDemo />
109+
代码见:<a target='_blank' href='https://github.com/umijs/hooks/blob/master/src/useAntdTable/SorterDemo.js'>https://github.com/umijs/hooks/blob/master/src/useAntdTable/SorterDemo.js</a>
110+
</>
111+
</Playground>
112+
103113
### 搜索表单与列表联动
104114

105115
<Playground>
@@ -133,6 +143,8 @@ const {
133143
}
134144
},
135145
refresh: () => void,
146+
sorter,
147+
filters,
136148
search?: {
137149
type: 'simple' | 'advance',
138150
changeType: () => void,
@@ -145,6 +157,8 @@ params:(
145157
service: ({
146158
current: number,
147159
pageSize: number,
160+
sorter,
161+
filters,
148162
[key: string]: any,
149163
}) => Promise<Result>,
150164
deps?: DependencyList = [],
@@ -164,27 +178,29 @@ params:(
164178

165179
### 结果
166180

167-
| 参数 | 说明 | 类型 | 默认值 |
168-
|---------------------------|---------------------------------|-------------------------------|--------------------|
181+
| 参数 | 说明 | 类型 | 默认值 |
182+
|--------------------------------|---------------------------------|-------------------------------|--------------------|
169183
| tableProps.loading | 是否正在加载 | boolean | false |
170184
| tableProps.dataSource | table 需要使用的数据 | array | - |
171185
| tableProps.onChange | antd Table 组件的 onChange 函数 | (e: PaginationConfig) => void | - |
172186
| tableProps.pagination.current | 当前页数 | number | 1 |
173187
| tableProps.pagination.pageSize | 每页数据量 | number | 10 |
174188
| tableProps.pagination.total | 数据总量 | number | 0 |
175-
| refresh | 刷新当前数据 | () => void | - |
176-
| search.type | 搜索类型 | 'simple' \| 'advance' |'simple' |
177-
| search.changeType | 触发搜索类型切换 | () => void | - |
178-
| search.submit | 触发搜索 | () => void | - |
179-
| search.reset | 重置搜索 | () => void | - |
189+
| sorter | 排序数据 | antd sorter | {} |
190+
| filters | 筛选数据 | antd filters | {} |
191+
| refresh | 刷新当前数据 | () => void | - |
192+
| search.type | 搜索类型 | 'simple' \ | 'advance'|'simple' |
193+
| search.changeType | 触发搜索类型切换 | () => void | - |
194+
| search.submit | 触发搜索 | () => void | - |
195+
| search.reset | 重置搜索 | () => void | - |
180196

181197

182198

183199
### 参数
184200

185201
| 参数 | 说明 | 类型 | 默认值 |
186202
|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|--------|
187-
| service | 请求数据的函数,函数参数为 current, pageSize,及当前搜索表单数据,返回数据期望同 options.formatResult。当然你可以通过传过传 options.formatResult 参数,后置格式化返回结果 | (Params)=> Promise | - |
203+
| service | 请求数据的函数,函数参数为 current, pageSize, sorter, filters,及当前搜索表单数据,返回数据期望同 options.formatResult。当然你可以通过传过传 options.formatResult 参数,后置格式化返回结果 | (Params)=> Promise | - |
188204
| deps | 依赖数组,如果 deps 变化,会触发 reload | any[] | [] |
189205
| options | 可选配置项,见 Options | - | - |
190206

src/useAntdTable/index.ts

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
import { WrappedFormUtils } from 'antd/lib/form/Form';
22
import { PaginationConfig } from 'antd/lib/pagination';
3-
import { DependencyList, useEffect, useReducer, useRef, useCallback } from 'react';
4-
import { useUpdateEffect } from 'react-use';
3+
import { SorterResult } from 'antd/lib/table';
4+
import {
5+
DependencyList,
6+
useCallback,
7+
useEffect,
8+
useReducer,
9+
useRef,
10+
useMemo,
11+
Reducer,
12+
} from 'react';
513
import useAsync from '../useAsync';
14+
import useUpdateEffect from '../useUpdateEffect';
15+
16+
const isEqual = require('lodash.isequal');
617

718
interface UseAntdTableFormUtils extends WrappedFormUtils {
819
getFieldInstance?: (name: string) => {};
@@ -13,7 +24,11 @@ export interface ReturnValue<Item> {
1324
table?: {
1425
dataSource: Item[];
1526
loading: boolean;
16-
onChange: (e: PaginationConfig) => void;
27+
onChange: (
28+
pagination: PaginationConfig,
29+
filters?: Record<keyof Item, string[]>,
30+
sorter?: SorterResult<Item>,
31+
) => void;
1732
pagination: {
1833
current: number;
1934
pageSize: number;
@@ -23,13 +38,19 @@ export interface ReturnValue<Item> {
2338
tableProps: {
2439
dataSource: Item[];
2540
loading: boolean;
26-
onChange: (e: PaginationConfig) => void;
41+
onChange: (
42+
pagination: PaginationConfig,
43+
filters?: Record<keyof Item, string[]>,
44+
sorter?: SorterResult<Item>,
45+
) => void;
2746
pagination: {
2847
current: number;
2948
pageSize: number;
3049
total: number;
3150
};
3251
};
52+
sorter: SorterResult<Item>;
53+
filters: Record<keyof Item, string[]>;
3354
refresh: () => void;
3455
search?: {
3556
type: 'simple' | 'advance';
@@ -63,7 +84,7 @@ interface FormData {
6384
[key: string]: any;
6485
}
6586

66-
class UseTableInitState {
87+
class UseTableInitState<Item> {
6788
// 搜索类型,简单、高级
6889
searchType: 'simple' | 'advance' = 'simple';
6990

@@ -86,16 +107,17 @@ class UseTableInitState {
86107
count = 0;
87108

88109
// 列表数据
89-
data: any[] = [];
90-
}
110+
data: Item[] = [];
91111

92-
// 初始值
93-
const initState = new UseTableInitState();
112+
filters: Record<keyof Item, string[]> = {} as Record<keyof Item, string[]>;
113+
114+
sorter: SorterResult<Item> = {} as SorterResult<Item>;
115+
}
94116

95117
// 缓存
96-
const cacheData: { [key: string]: UseTableInitState } = {};
118+
const cacheData: { [key: string]: any } = {};
97119

98-
const reducer = (state = initState, action: { type: string; payload?: {} }) => {
120+
const reducer = <Item>(state: UseTableInitState<Item>, action: { type: string; payload?: {} }) => {
99121
switch (action.type) {
100122
case 'updateState':
101123
return { ...state, ...action.payload };
@@ -123,13 +145,18 @@ function useAntdTable<Result, Item>(
123145
? deps
124146
: options || {}) as Options<Result, Item>;
125147

148+
const initState = useMemo(() => new UseTableInitState<Item>(), []);
149+
126150
const { defaultPageSize = 10, id, form, formatResult } = _options;
127-
const [state, dispatch] = useReducer(reducer, { ...initState, pageSize: defaultPageSize });
151+
const [state, dispatch] = useReducer<Reducer<UseTableInitState<Item>, any>>(reducer, {
152+
...initState,
153+
pageSize: defaultPageSize,
154+
});
128155

129156
/* 临时记录切换前的表单数据 */
130157
const tempFieldsValueRef = useRef<FormData>({});
131158

132-
const stateRef = useRef<UseTableInitState>(({} as unknown) as UseTableInitState);
159+
const stateRef = useRef({} as UseTableInitState<Item>);
133160
stateRef.current = state;
134161
const { run, loading } = useAsync(fn, _deps, {
135162
manual: true,
@@ -166,6 +193,8 @@ function useAntdTable<Result, Item>(
166193
searchType: cache.searchType,
167194
activeFormData: cache.activeFormData,
168195
formData: cache.formData,
196+
filters: cache.filters,
197+
sorter: cache.sorter,
169198
count: state.count + 1,
170199
},
171200
});
@@ -198,11 +227,19 @@ function useAntdTable<Result, Item>(
198227
formattedData[key] = state.activeFormData[key];
199228
}
200229
});
201-
run({
230+
231+
const params: any = {
202232
current: state.current,
203233
pageSize: state.pageSize,
204234
...formattedData,
205-
}).then(res => {
235+
};
236+
if (state.filters) {
237+
params.filters = state.filters;
238+
}
239+
if (state.sorter) {
240+
params.sorter = state.sorter;
241+
}
242+
run(params).then(res => {
206243
const payload = formatResult ? formatResult(res) : res;
207244
dispatch({
208245
type: 'updateState',
@@ -303,15 +340,26 @@ function useAntdTable<Result, Item>(
303340
});
304341
}, [state.searchType]);
305342

306-
// 表格翻页
343+
// 表格翻页 排序 筛选等
307344
const changeTable = useCallback(
308-
(e: PaginationConfig) => {
345+
(
346+
p: PaginationConfig,
347+
f: Record<keyof Item, string[]> = {} as Record<keyof Item, string[]>,
348+
s: SorterResult<Item> = {} as SorterResult<Item>,
349+
) => {
350+
/* 如果 filter,或者 sort 变化,就初始化 current */
351+
const needReload =
352+
!isEqual(f, state.filters) ||
353+
s.field !== state.sorter.field ||
354+
s.order !== state.sorter.order;
309355
dispatch({
310356
type: 'updateState',
311357
payload: {
312-
current: e.current,
313-
pageSize: e.pageSize,
358+
current: needReload ? 1 : p.current,
359+
pageSize: p.pageSize,
314360
count: state.count + 1,
361+
filters: f,
362+
sorter: s,
315363
},
316364
});
317365
},
@@ -340,6 +388,8 @@ function useAntdTable<Result, Item>(
340388
total: state.total,
341389
},
342390
},
391+
sorter: state.sorter,
392+
filters: state.filters,
343393
refresh,
344394
};
345395
if (form) {

0 commit comments

Comments
 (0)