mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-09 21:09:19 +08:00
1fda3ece9e
* fix: demo ts type * mend * Update select-users.md
2.7 KiB
2.7 KiB
order | title | ||||
---|---|---|---|---|---|
12 |
|
zh-CN
一个带有远程搜索,防抖控制,请求时序控制,加载状态的多选示例。
en-US
A complete multiple select sample with remote search, debounce fetch, ajax callback order flow, and loading state.
import { Select, Spin } from 'antd';
import type { SelectProps } from 'antd/es/select';
import debounce from 'lodash/debounce';
import React, { useMemo, useRef, useState } from 'react';
export interface DebounceSelectProps<ValueType = any>
extends Omit<SelectProps<ValueType | ValueType[]>, 'options' | 'children'> {
fetchOptions: (search: string) => Promise<ValueType[]>;
debounceTimeout?: number;
}
function DebounceSelect<
ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any,
>({ fetchOptions, debounceTimeout = 800, ...props }: DebounceSelectProps<ValueType>) {
const [fetching, setFetching] = useState(false);
const [options, setOptions] = useState<ValueType[]>([]);
const fetchRef = useRef(0);
const debounceFetcher = useMemo(() => {
const loadOptions = (value: string) => {
fetchRef.current += 1;
const fetchId = fetchRef.current;
setOptions([]);
setFetching(true);
fetchOptions(value).then(newOptions => {
if (fetchId !== fetchRef.current) {
// for fetch callback order
return;
}
setOptions(newOptions);
setFetching(false);
});
};
return debounce(loadOptions, debounceTimeout);
}, [fetchOptions, debounceTimeout]);
return (
<Select
labelInValue
filterOption={false}
onSearch={debounceFetcher}
notFoundContent={fetching ? <Spin size="small" /> : null}
{...props}
options={options}
/>
);
}
// Usage of DebounceSelect
interface UserValue {
label: string;
value: string;
}
async function fetchUserList(username: string): Promise<UserValue[]> {
console.log('fetching user', username);
return fetch('https://randomuser.me/api/?results=5')
.then(response => response.json())
.then(body =>
body.results.map(
(user: { name: { first: string; last: string }; login: { username: string } }) => ({
label: `${user.name.first} ${user.name.last}`,
value: user.login.username,
}),
),
);
}
const App: React.FC = () => {
const [value, setValue] = useState<UserValue[]>([]);
return (
<DebounceSelect
mode="multiple"
value={value}
placeholder="Select users"
fetchOptions={fetchUserList}
onChange={newValue => {
setValue(newValue as UserValue[]);
}}
style={{ width: '100%' }}
/>
);
};
export default App;