diff --git a/packages/components/select/_example/remote-search.tsx b/packages/components/select/_example/remote-search.tsx
index 9d911cba02..dfb8db0313 100644
--- a/packages/components/select/_example/remote-search.tsx
+++ b/packages/components/select/_example/remote-search.tsx
@@ -1,53 +1,73 @@
-import React, { useState } from 'react';
-import { Select } from 'tdesign-react';
+import React, { useEffect, useState } from 'react';
+import { Select, Space } from 'tdesign-react';
+
+const OPTIONS = Array.from({ length: 20 }).map((_, i) => ({
+ value: `t${i + 1}`,
+ label: `Tencent_${i + 1}`,
+}));
const RemoteSearchSelect = () => {
- const [value, setValue] = useState('');
+ const [singleLoading, setSingleLoading] = useState(false);
+ const [singleOptions, setSingleOptions] = useState([]);
+ const [singleValue, setSingleValue] = useState('');
- const [loading, setLoading] = useState(false);
- const [options, setOptions] = useState([]);
+ const [multipleLoading, setMultipleLoading] = useState(false);
+ const [multipleOptions, setMultipleOptions] = useState([]);
+ const [multipleValue, setMultipleValue] = useState([]);
- const onChange = (value: string) => {
- setValue(value);
- };
+ useEffect(() => {
+ setSingleLoading(true);
+ setMultipleLoading(true);
+
+ setTimeout(() => {
+ setSingleOptions(OPTIONS);
+ setSingleLoading(false);
+ setSingleValue(OPTIONS[0].value);
+ setMultipleOptions(OPTIONS);
+ setMultipleLoading(false);
+ setMultipleValue([OPTIONS[0].value, OPTIONS[1].value]);
+ }, 500);
+ }, []);
- const handleRemoteSearch = (search: string) => {
- setLoading(true);
+ const handleSingle = (search: string) => {
+ setSingleLoading(true);
+ setTimeout(() => {
+ const filtered = OPTIONS.filter((item) => item.label.includes(search));
+ setSingleOptions(filtered);
+ setSingleLoading(false);
+ }, 500);
+ };
+ const handleMultiple = (search: string) => {
+ setMultipleLoading(true);
setTimeout(() => {
- setLoading(false);
- let options = [];
- if (search) {
- options = [
- {
- value: `腾讯_test1`,
- label: `腾讯_test1`,
- },
- {
- value: `腾讯_test2`,
- label: `腾讯_test2`,
- },
- {
- value: `腾讯_test3`,
- label: `腾讯_test3`,
- },
- ].filter((item) => item.label.includes(search));
- }
-
- setOptions(options);
+ const filtered = OPTIONS.filter((item) => item.label.includes(search));
+ setMultipleOptions(filtered);
+ setMultipleLoading(false);
}, 500);
};
return (
-
+
+
+
+
);
};
diff --git a/packages/components/select/base/Select.tsx b/packages/components/select/base/Select.tsx
index f031d9d3d4..c90307b97a 100644
--- a/packages/components/select/base/Select.tsx
+++ b/packages/components/select/base/Select.tsx
@@ -130,6 +130,13 @@ const Select = forwardRefWithStatics(
if (disabled) return;
visible && toggleIsScrolling(false);
!visible && onInputChange('', { trigger: 'blur' });
+
+ if (visible && isFunction(onSearch) && !inputValue) {
+ // @ts-ignore
+ // 实际是由 click 触发而非键盘事件,待补充类型
+ onSearch('', { e: ctx.e });
+ }
+
setShowPopup(visible, ctx);
};
diff --git a/packages/components/select/hooks/useOptions.ts b/packages/components/select/hooks/useOptions.ts
index 8f6013af72..dff924e77c 100644
--- a/packages/components/select/hooks/useOptions.ts
+++ b/packages/components/select/hooks/useOptions.ts
@@ -1,18 +1,21 @@
-import { get } from 'lodash-es';
import React, { ReactElement, ReactNode, useEffect, useState } from 'react';
+import { get } from 'lodash-es';
import Option from '../base/Option';
import OptionGroup from '../base/OptionGroup';
import { getKeyMapping, getValueToOption, type ValueToOption } from '../util/helper';
import type { SelectKeysType, SelectOption, SelectOptionGroup, SelectValue, TdOptionProps } from '../type';
+type OptionValueType = SelectValue;
+
export function isSelectOptionGroup(option: SelectOption): option is SelectOptionGroup {
return !!option && 'group' in option && 'children' in option;
}
-type OptionValueType = SelectValue;
+export function isValueSelected(v: SelectValue, key: string, valueType: string, valueKey: string) {
+ return valueType === 'value' ? String(v) === String(key) : get(v, valueKey) === key;
+}
-// 处理 options 的逻辑
function useOptions(
keys: SelectKeysType,
options: SelectOption[],
@@ -66,7 +69,25 @@ function useOptions(
setCurrentOptions(transformedOptions);
setTmpPropOptions(transformedOptions);
- setValueToOption(getValueToOption(children as ReactElement, options as TdOptionProps[], keys) || {});
+ setValueToOption((prevValueToOption) => {
+ const newValueToOption = getValueToOption(children as ReactElement, options as TdOptionProps[], keys) || {};
+ const { valueKey } = getKeyMapping(keys);
+ const mergedValueToOption = { ...newValueToOption };
+
+ // 保持之前选中的 option 在映射中,避免远程搜索时,状态丢失
+ Object.keys(prevValueToOption).forEach((key) => {
+ if (mergedValueToOption[key]) return;
+ const isSelected = Array.isArray(value)
+ ? value.some((v) => isValueSelected(v, key, valueType, valueKey))
+ : isValueSelected(value, key, valueType, valueKey);
+
+ if (isSelected) {
+ mergedValueToOption[key] = prevValueToOption[key];
+ }
+ });
+
+ return mergedValueToOption;
+ });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [options, keys, children, reserveKeyword]);
diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap
index 6e7c6b6946..025daa98ac 100644
--- a/test/snap/__snapshots__/csr.test.jsx.snap
+++ b/test/snap/__snapshots__/csr.test.jsx.snap
@@ -88567,44 +88567,124 @@ exports[`csr snapshot test > csr test packages/components/select/_example/prefix
exports[`csr snapshot test > csr test packages/components/select/_example/remote-search.tsx 1`] = `
@@ -150176,7 +150256,7 @@ exports[`ssr snapshot test > ssr test packages/components/select/_example/popup-
exports[`ssr snapshot test > ssr test packages/components/select/_example/prefix.tsx 1`] = `""`;
-exports[`ssr snapshot test > ssr test packages/components/select/_example/remote-search.tsx 1`] = `""`;
+exports[`ssr snapshot test > ssr test packages/components/select/_example/remote-search.tsx 1`] = `""`;
exports[`ssr snapshot test > ssr test packages/components/select/_example/scroll-bottom.tsx 1`] = `""`;
diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap
index fdecc07bb4..948f21a51e 100644
--- a/test/snap/__snapshots__/ssr.test.jsx.snap
+++ b/test/snap/__snapshots__/ssr.test.jsx.snap
@@ -844,7 +844,7 @@ exports[`ssr snapshot test > ssr test packages/components/select/_example/popup-
exports[`ssr snapshot test > ssr test packages/components/select/_example/prefix.tsx 1`] = `""`;
-exports[`ssr snapshot test > ssr test packages/components/select/_example/remote-search.tsx 1`] = `""`;
+exports[`ssr snapshot test > ssr test packages/components/select/_example/remote-search.tsx 1`] = `""`;
exports[`ssr snapshot test > ssr test packages/components/select/_example/scroll-bottom.tsx 1`] = `""`;