LazySelect.tsx
3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { Select, Spin } from 'antd';
import debounce from 'lodash/debounce';
import difference from 'lodash/difference';
import { useEffect, useState } from 'react';
/**
* 懒加载 Select ,适用于数据超大的下拉框
* @param {Select 官方属性} props
*/
const LazySelect = (props) => {
const { value, onChange, query, pageSize } = props;
// 清除 porps 中 query,避免控制台警告
const selectProps = { ...props, query: undefined };
const [selected, setSelected] = useState(value);
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [current, setCurrent] = useState(1);
const [total, setTotal] = useState(0);
const [searchText] = useState('');
const getSelectedArray = (obj) => {
let selectedValues = obj;
// 如果是单选,将值封装为数组
if (obj && obj instanceof Array === false) {
selectedValues = [obj];
}
return selectedValues;
};
// 添加 300 毫秒防抖
const handleQuery = debounce(async (param) => {
setLoading(true);
const resp = await query(param);
const resData = resp.data;
let options = resData?.data?.map((p: any) => {
return {
...p,
label: p.productName,
value: p.productName,
key: p.id,
};
});
// 搜索服务端异步加载
// const handleSearch = (filter) => {
// setSearchText(filter);
// handleQuery({
// filter,
// selectedValues: getSelectedArray(selected),
// pageSize,
// current
// });
// };
//第一个商品默认为要新增的商品
// if (searchValue?.trim() !== "") {
// options.unshift({ productName: searchValue, type: "add", label: searchValue, value: searchValue })
// }
// return options;
setTotal(resData.total);
setData(data.concat(options));
setLoading(false);
}, 300);
// 组件初始化时加载一次数据
useEffect(() => {
handleQuery({
filter: '',
selectedValues: getSelectedArray(value),
});
}, []);
// 外部注入的 value 变化后,如果 value 在 data 中不存在,则加载数据
useEffect(() => {
setSelected(value);
const dataKeys = data.map((item) => item.value);
const diff = difference(getSelectedArray(value), dataKeys);
if (diff && diff.length > 0) {
handleQuery({
filter: '',
selectedValues: getSelectedArray(value),
});
}
}, [value]);
const keywordChange = (newWord: string) => {
setData([]);
setTotal(0);
setCurrent(1);
handleSearch(newWord);
};
const handleChange = (newValue, option) => {
setSelected(newValue);
if (onChange) {
// 将值通过 onChange 传递到外部
onChange(newValue, option);
}
};
const scrollEnd = (e) => {
e.persist();
const { target } = e;
// 滚动 触底 看接口是否还有剩余的值没传过来
if (target.scrollTop + target.offsetHeight === target.scrollHeight) {
if (current * pageSize < total) {
setCurrent(current + 1);
handleSearch(searchText);
}
}
};
return (
<Select
{...selectProps}
value={selected}
loading={loading}
onSearch={keywordChange}
onChange={handleChange}
onPopupScroll={scrollEnd}
filterOption={false}
options={data}
showSearch
showArrow
notFoundContent={loading ? <Spin size="small" /> : null}
>
{/* {data.map(d => (
<Option key={d.value} title={d.label}>
{d.label}
</Option>
))} */}
</Select>
);
};
export default LazySelect;