|
|
|
|
@ -1,29 +1,41 @@
|
|
|
|
|
import React, { useMemo, useRef, useState } from 'react';
|
|
|
|
|
import React, { useMemo, useRef, useState, useEffect } from 'react';
|
|
|
|
|
import { Select, Spin } from 'antd';
|
|
|
|
|
import { debounce, objectMapper } from '@/utils/commons';
|
|
|
|
|
|
|
|
|
|
function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) {
|
|
|
|
|
function DebounceSelect({ fetchOptions, debounceTimeout = 500, initLoad = false, defaultOptions=[], ...props }) {
|
|
|
|
|
const [fetching, setFetching] = useState(false);
|
|
|
|
|
const [options, setOptions] = useState([]);
|
|
|
|
|
const fetchRef = useRef(0);
|
|
|
|
|
|
|
|
|
|
// 首次加载获取选项
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
setOptions(defaultOptions);
|
|
|
|
|
if (initLoad && defaultOptions.length===0) {
|
|
|
|
|
loadOptions(' ');
|
|
|
|
|
}
|
|
|
|
|
}, [initLoad]);
|
|
|
|
|
|
|
|
|
|
const loadOptions = (value) => {
|
|
|
|
|
fetchRef.current += 1;
|
|
|
|
|
const fetchId = fetchRef.current;
|
|
|
|
|
if (value) setOptions([]);
|
|
|
|
|
setFetching(true);
|
|
|
|
|
fetchOptions(value).then((newOptions) => {
|
|
|
|
|
const mapperOptions = newOptions.map(ele => objectMapper(ele, props.map));
|
|
|
|
|
if (fetchId !== fetchRef.current) {
|
|
|
|
|
// for fetch callback order
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
setOptions(mapperOptions);
|
|
|
|
|
setFetching(false);
|
|
|
|
|
props.onFetch && props.onFetch(mapperOptions);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const debounceFetcher = useMemo(() => {
|
|
|
|
|
const loadOptions = (value) => {
|
|
|
|
|
fetchRef.current += 1;
|
|
|
|
|
const fetchId = fetchRef.current;
|
|
|
|
|
setOptions([]);
|
|
|
|
|
setFetching(true);
|
|
|
|
|
fetchOptions(value).then((newOptions) => {
|
|
|
|
|
const mapperOptions = newOptions.map(ele => objectMapper(ele, props.map));
|
|
|
|
|
if (fetchId !== fetchRef.current) {
|
|
|
|
|
// for fetch callback order
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
setOptions(mapperOptions);
|
|
|
|
|
setFetching(false);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
return debounce(loadOptions, debounceTimeout);
|
|
|
|
|
}, [fetchOptions, debounceTimeout]);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Select
|
|
|
|
|
labelInValue
|
|
|
|
|
@ -32,7 +44,8 @@ function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) {
|
|
|
|
|
allowClear
|
|
|
|
|
maxTagCount={1}
|
|
|
|
|
loading={fetching}
|
|
|
|
|
dropdownStyle={{width: '20rem'}}
|
|
|
|
|
// dropdownStyle={{width: '20rem'}}
|
|
|
|
|
styles={{ root: { width: 'min(20rem, 100%)' }, popup: { root: { width: '20rem' } } }}
|
|
|
|
|
{...props}
|
|
|
|
|
onSearch={debounceFetcher}
|
|
|
|
|
notFoundContent={fetching ? <Spin size='small' /> : null}
|
|
|
|
|
|