Skip to content

Commit 298b463

Browse files
authored
feat(useModal): develop useModal (#427)
* feat(useModal): develop useModal and improve example
1 parent 2da23a9 commit 298b463

File tree

5 files changed

+205
-0
lines changed

5 files changed

+205
-0
lines changed

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ export { default as Table } from './table';
3232
export { default as TinyTag } from './tinyTag';
3333
export { default as useIntersectionObserver } from './useIntersectionObserver';
3434
export { default as useList } from './useList';
35+
export { default as useModal } from './useModal';
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { act } from '@testing-library/react';
2+
import { renderHook } from '@testing-library/react-hooks';
3+
4+
import useModal from '..';
5+
6+
describe('Test useModal hook', () => {
7+
it('Should ensure initial data', async () => {
8+
const { result } = renderHook(() => useModal());
9+
expect(result.current.visible).toBeFalsy();
10+
expect(result.current.record).toBeUndefined();
11+
expect(result.current.open).toBeDefined();
12+
expect(result.current.close).toBeDefined();
13+
});
14+
15+
it('Should support open/close modal', async () => {
16+
const record = {
17+
id: '1',
18+
name: 'John Brown',
19+
age: 32,
20+
address: 'New York No. 1 Lake Park',
21+
};
22+
const { result } = renderHook(() => useModal());
23+
act(() => {
24+
result.current.open(record);
25+
});
26+
27+
expect(result.current.visible).toBeTruthy();
28+
expect(result.current.record).toEqual(record);
29+
30+
act(() => {
31+
result.current.close();
32+
});
33+
34+
expect(result.current.visible).toBeFalsy();
35+
expect(result.current.record).toBeUndefined();
36+
});
37+
});

src/useModal/demos/basic.tsx

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import React, { useEffect } from 'react';
2+
import { Button, Form, Input, Modal, Table } from 'antd';
3+
import type { ColumnType } from 'antd/lib/table';
4+
5+
import useModal from '..';
6+
7+
interface IDataSource {
8+
id: string;
9+
name: string;
10+
age: number;
11+
address: string;
12+
}
13+
14+
const data: IDataSource[] = [
15+
{
16+
id: '1',
17+
name: 'John Brown',
18+
age: 32,
19+
address: 'New York No. 1 Lake Park',
20+
},
21+
{
22+
id: '2',
23+
name: 'Jim Green',
24+
age: 42,
25+
address: 'London No. 1 Lake Park',
26+
},
27+
{
28+
id: '3',
29+
name: 'Joe Black',
30+
age: 52,
31+
address: 'Sydney No. 1 Lake Park',
32+
},
33+
{
34+
id: '4',
35+
name: 'Jim Red',
36+
age: 62,
37+
address: 'London No. 2 Lake Park',
38+
},
39+
];
40+
41+
export default () => {
42+
const modal = useModal<IDataSource>();
43+
const [form] = Form.useForm<IDataSource>();
44+
45+
const columns: ColumnType<IDataSource>[] = [
46+
{
47+
key: 'name',
48+
title: 'name',
49+
dataIndex: 'name',
50+
},
51+
{
52+
key: 'age',
53+
title: 'age',
54+
dataIndex: 'age',
55+
},
56+
{
57+
key: 'address',
58+
title: 'address',
59+
dataIndex: 'address',
60+
},
61+
{
62+
key: 'operation',
63+
title: '操作',
64+
render: (_, record) => {
65+
return (
66+
<Button
67+
type="link"
68+
onClick={() => {
69+
modal.open(record);
70+
}}
71+
>
72+
编辑
73+
</Button>
74+
);
75+
},
76+
},
77+
];
78+
79+
useEffect(() => {
80+
if (modal.visible) {
81+
form.setFieldsValue({
82+
name: modal.record?.name,
83+
age: modal.record?.age,
84+
address: modal.record?.address,
85+
});
86+
} else {
87+
form.resetFields();
88+
}
89+
}, [modal.record, modal.visible]);
90+
91+
return (
92+
<>
93+
<Table
94+
columns={columns}
95+
size="small"
96+
scroll={{ y: 200 }}
97+
dataSource={data}
98+
rowKey="uuid"
99+
bordered
100+
/>
101+
<Modal
102+
title="修改信息"
103+
visible={modal.visible}
104+
onOk={modal.close}
105+
onCancel={modal.close}
106+
>
107+
<Form form={form}>
108+
<Form.Item label="姓名" name="name">
109+
<Input />
110+
</Form.Item>
111+
<Form.Item label="年龄" name="age">
112+
<Input />
113+
</Form.Item>
114+
<Form.Item label="地址" name="address">
115+
<Input />
116+
</Form.Item>
117+
</Form>
118+
</Modal>
119+
</>
120+
);
121+
};

src/useModal/index.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: useModal 保存当前数据并打开弹框
3+
group: Hooks
4+
toc: content
5+
---
6+
7+
# useModal
8+
9+
## 何时使用
10+
11+
保存当前数据并打开弹框
12+
13+
## 示例
14+
15+
<code src="./demos/basic.tsx" title="基础使用"></code>
16+
17+
## API
18+
19+
### Returns
20+
21+
| 参数 | 说明 | 类型 | 默认值 |
22+
| ------- | -------- | ---------------------- | ----------- |
23+
| visible | 是否可见 | `boolean` | `false` |
24+
| record | 选中数据 | `T \| undefined` | `undefined` |
25+
| open | 打开 | `(record?: T) => void` | - |
26+
| close | 关闭 | `() => void` | - |

src/useModal/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { useState } from 'react';
2+
3+
const useModal = <T>() => {
4+
const [visible, setVisible] = useState(false);
5+
const [record, setRecord] = useState<T | undefined>(undefined);
6+
7+
const open = (record?: T) => {
8+
setRecord(record);
9+
setVisible(true);
10+
};
11+
12+
const close = () => {
13+
setRecord(undefined);
14+
setVisible(false);
15+
};
16+
17+
return { visible, record, open, close };
18+
};
19+
20+
export default useModal;

0 commit comments

Comments
 (0)