You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.5 KiB
JavaScript
50 lines
1.5 KiB
JavaScript
import React, { useMemo, useRef, useState } from 'react';
|
|
import { Select, Spin } from 'antd';
|
|
import { debounce, objectMapper } from '@/utils/commons';
|
|
|
|
function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) {
|
|
const [fetching, setFetching] = useState(false);
|
|
const [options, setOptions] = useState([]);
|
|
const fetchRef = useRef(0);
|
|
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
|
|
filterOption={false}
|
|
showSearch
|
|
allowClear
|
|
maxTagCount={1}
|
|
dropdownStyle={{width: '20rem'}}
|
|
{...props}
|
|
onSearch={debounceFetcher}
|
|
notFoundContent={fetching ? <Spin size='small' /> : null}
|
|
optionFilterProp='label'
|
|
>
|
|
{options.map((d) => (
|
|
<Select.Option key={d.value} title={d.label}>
|
|
{d.label}
|
|
</Select.Option>
|
|
))}
|
|
</Select>
|
|
);
|
|
}
|
|
|
|
export default DebounceSelect;
|