Skip to content

Commit d532107

Browse files
authored
chore: optimize search performance (#586)
1 parent e73d080 commit d532107

File tree

5 files changed

+30
-38
lines changed

5 files changed

+30
-38
lines changed

src/generate.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ export default function generateSelector<
371371
React.useImperativeHandle(ref, () => ({
372372
focus: selectorRef.current.focus,
373373
blur: selectorRef.current.blur,
374-
scrollTo: listRef.current?.scrollTo,
374+
scrollTo: listRef.current?.scrollTo as ScrollTo,
375375
}));
376376

377377
// ============================= Value ==============================
@@ -380,7 +380,9 @@ export default function generateSelector<
380380
});
381381

382382
/** Unique raw values */
383-
const mergedRawValue = useMemo<RawValueType[]>(
383+
const [mergedRawValue, mergedValueMap] = useMemo<
384+
[RawValueType[], Map<RawValueType, LabelValueType>]
385+
>(
384386
() =>
385387
toInnerValue(mergedValue, {
386388
labelInValue: mergedLabelInValue,
@@ -431,7 +433,7 @@ export default function generateSelector<
431433
[mergedOptions],
432434
);
433435

434-
const getValueOption = useCacheOptions(mergedRawValue, mergedFlattenOptions);
436+
const getValueOption = useCacheOptions(mergedFlattenOptions);
435437

436438
// Display options for OptionList
437439
const displayOptions = useMemo<OptionsType>(() => {
@@ -476,7 +478,7 @@ export default function generateSelector<
476478
const valueOptions = getValueOption([val]);
477479
const displayValue = getLabeledValue(val, {
478480
options: valueOptions,
479-
prevValue: mergedValue,
481+
prevValueMap: mergedValueMap,
480482
labelInValue: mergedLabelInValue,
481483
optionLabelProp: mergedOptionLabelProp,
482484
});
@@ -511,7 +513,7 @@ export default function generateSelector<
511513
const selectValue = (mergedLabelInValue
512514
? getLabeledValue(newValue, {
513515
options: newValueOption,
514-
prevValue: mergedValue,
516+
prevValueMap: mergedValueMap,
515517
labelInValue: mergedLabelInValue,
516518
optionLabelProp: mergedOptionLabelProp,
517519
})
@@ -546,7 +548,7 @@ export default function generateSelector<
546548
labelInValue: mergedLabelInValue,
547549
options: newRawValuesOptions,
548550
getLabeledValue,
549-
prevValue: mergedValue,
551+
prevValueMap: mergedValueMap,
550552
optionLabelProp: mergedOptionLabelProp,
551553
});
552554

src/hooks/useCacheOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default function useCacheOptions<
88
key?: Key;
99
disabled?: boolean;
1010
}[]
11-
>(values: RawValueType[], options: FlattenOptionsType<OptionsType>) {
11+
>(options: FlattenOptionsType<OptionsType>) {
1212
const prevOptionMapRef = React.useRef<Map<RawValueType, FlattenOptionsType<OptionsType>[number]>>(
1313
null,
1414
);
@@ -22,7 +22,7 @@ export default function useCacheOptions<
2222
map.set(value, item);
2323
});
2424
return map;
25-
}, [values, options]);
25+
}, [options]);
2626

2727
prevOptionMapRef.current = optionMap;
2828

src/interface/generator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export type GetLabeledValue<FOT extends FlattenOptionsType> = (
3838
value: RawValueType,
3939
config: {
4040
options: FOT;
41-
prevValue: DefaultValueType;
41+
prevValueMap: Map<RawValueType, LabelValueType>;
4242
labelInValue: boolean;
4343
optionLabelProp: string;
4444
},

src/utils/commonUtil.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,26 @@ export function toArray<T>(value: T | T[]): T[] {
1919
export function toInnerValue(
2020
value: DefaultValueType,
2121
{ labelInValue, combobox }: { labelInValue: boolean; combobox: boolean },
22-
): RawValueType[] {
22+
): [RawValueType[], Map<RawValueType, LabelValueType>] {
23+
const valueMap = new Map<RawValueType, LabelValueType>();
24+
2325
if (value === undefined || (value === '' && combobox)) {
24-
return [];
26+
return [[], valueMap];
2527
}
2628

2729
const values = Array.isArray(value) ? value : [value];
30+
let rawValues = values as RawValueType[];
2831

2932
if (labelInValue) {
30-
return (values as LabelValueType[]).map(
31-
({ key, value: val }: LabelValueType) => (val !== undefined ? val : key),
32-
);
33+
rawValues = (values as LabelValueType[]).map((itemValue: LabelValueType) => {
34+
const { key, value: val } = itemValue;
35+
const finalVal = val !== undefined ? val : key;
36+
valueMap.set(finalVal, itemValue);
37+
return finalVal;
38+
});
3339
}
3440

35-
return values as RawValueType[];
41+
return [rawValues, valueMap];
3642
}
3743

3844
/**
@@ -43,15 +49,15 @@ export function toOuterValues<FOT extends FlattenOptionsType>(
4349
{
4450
optionLabelProp,
4551
labelInValue,
46-
prevValue,
52+
prevValueMap,
4753
options,
4854
getLabeledValue,
4955
}: {
5056
optionLabelProp: string;
5157
labelInValue: boolean;
5258
getLabeledValue: GetLabeledValue<FOT>;
5359
options: FOT;
54-
prevValue: DefaultValueType;
60+
prevValueMap: Map<RawValueType, LabelValueType>;
5561
},
5662
): RawValueType[] | LabelValueType[] {
5763
let values: DefaultValueType = valueList;
@@ -60,7 +66,7 @@ export function toOuterValues<FOT extends FlattenOptionsType>(
6066
values = values.map(val =>
6167
getLabeledValue(val, {
6268
options,
63-
prevValue,
69+
prevValueMap,
6470
labelInValue,
6571
optionLabelProp,
6672
}),
@@ -77,11 +83,7 @@ export function removeLastEnabledValue<
7783
const newValues = [...values];
7884

7985
let removeIndex: number;
80-
for (
81-
removeIndex = measureValues.length - 1;
82-
removeIndex >= 0;
83-
removeIndex -= 1
84-
) {
86+
for (removeIndex = measureValues.length - 1; removeIndex >= 0; removeIndex -= 1) {
8587
if (!measureValues[removeIndex].disabled) {
8688
break;
8789
}
@@ -101,9 +103,7 @@ export function removeLastEnabledValue<
101103
}
102104

103105
export const isClient =
104-
typeof window !== 'undefined' &&
105-
window.document &&
106-
window.document.documentElement;
106+
typeof window !== 'undefined' && window.document && window.document.documentElement;
107107

108108
/** Is client side and not jsdom */
109109
export const isBrowserClient = process.env.NODE_ENV !== 'test' && isClient;

src/utils/valueUtil.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,24 +119,14 @@ export function findValueOption(
119119

120120
export const getLabeledValue: GetLabeledValue<FlattenOptionData[]> = (
121121
value,
122-
{ options, prevValue, labelInValue, optionLabelProp },
122+
{ options, prevValueMap, labelInValue, optionLabelProp },
123123
) => {
124124
const item = findValueOption([value], options)[0];
125125
const result: LabelValueType = {
126126
value,
127127
};
128128

129-
let prevValItem: LabelValueType;
130-
const prevValues = toArray<RawValueType | LabelValueType>(prevValue);
131-
if (labelInValue) {
132-
prevValItem = prevValues.find((prevItem: LabelValueType) => {
133-
if (typeof prevItem === 'object' && 'value' in prevItem) {
134-
return prevItem.value === value;
135-
}
136-
// [Legacy] Support `key` as `value`
137-
return prevItem.key === value;
138-
}) as LabelValueType;
139-
}
129+
const prevValItem: LabelValueType = labelInValue ? prevValueMap.get(value) : undefined;
140130

141131
if (prevValItem && typeof prevValItem === 'object' && 'label' in prevValItem) {
142132
result.label = prevValItem.label;

0 commit comments

Comments
 (0)