Skip to content

Commit 4e6cea8

Browse files
committed
fix(useOptions): retain selected options during remote searches
1 parent b524dff commit 4e6cea8

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

packages/components/select/hooks/useOptions.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
import { get } from 'lodash-es';
21
import React, { ReactElement, ReactNode, useEffect, useState } from 'react';
2+
import { get } from 'lodash-es';
33
import Option from '../base/Option';
44
import OptionGroup from '../base/OptionGroup';
55
import { getKeyMapping, getValueToOption, type ValueToOption } from '../util/helper';
66

77
import type { SelectKeysType, SelectOption, SelectOptionGroup, SelectValue, TdOptionProps } from '../type';
88

9+
type OptionValueType = SelectValue<SelectOption>;
10+
911
export function isSelectOptionGroup(option: SelectOption): option is SelectOptionGroup {
1012
return !!option && 'group' in option && 'children' in option;
1113
}
1214

13-
type OptionValueType = SelectValue<SelectOption>;
15+
export function isValueSelected(v: SelectValue, key: string, valueType: string, valueKey: string) {
16+
return valueType === 'value' ? String(v) === String(key) : get(v, valueKey) === key;
17+
}
1418

15-
// 处理 options 的逻辑
1619
function useOptions(
1720
keys: SelectKeysType,
1821
options: SelectOption[],
@@ -66,9 +69,28 @@ function useOptions(
6669
setCurrentOptions(transformedOptions);
6770
setTmpPropOptions(transformedOptions);
6871

69-
setValueToOption(getValueToOption(children as ReactElement, options as TdOptionProps[], keys) || {});
72+
setValueToOption((prevValueToOption) => {
73+
const newValueToOption = getValueToOption(children as ReactElement, options as TdOptionProps[], keys) || {};
74+
const { valueKey } = getKeyMapping(keys);
75+
const mergedValueToOption = { ...newValueToOption };
76+
77+
// 保持之前选中的 option 在映射中
78+
// 避免远程搜索时,选中的 option 状态丢失
79+
Object.keys(prevValueToOption).forEach((key) => {
80+
if (mergedValueToOption[key]) return;
81+
const isSelected = Array.isArray(value)
82+
? value.some((v) => isValueSelected(v, key, valueType, valueKey))
83+
: isValueSelected(value, key, valueType, valueKey);
84+
85+
if (isSelected) {
86+
mergedValueToOption[key] = prevValueToOption[key];
87+
}
88+
});
89+
90+
return mergedValueToOption;
91+
});
7092
// eslint-disable-next-line react-hooks/exhaustive-deps
71-
}, [options, keys, children, reserveKeyword]);
93+
}, [options, keys, children, reserveKeyword, value, valueType]);
7294

7395
// 同步 value 对应的 options
7496
useEffect(() => {

0 commit comments

Comments
 (0)