Skip to content

Commit ba42885

Browse files
committed
fix(useSingle): improve label handling and typing state management
1 parent 259ed00 commit ba42885

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

packages/components/select-input/useSingle.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useRef, useState } from 'react';
1+
import React, { useEffect, useMemo, useRef, useState } from 'react';
22

33
import classNames from 'classnames';
44
import { isObject, pick } from 'lodash-es';
@@ -45,23 +45,29 @@ function getOptionLabel(value: TdSelectInputProps['value'], keys: TdSelectInputP
4545

4646
export default function useSingle(props: TdSelectInputProps) {
4747
const { value, loading } = props;
48-
49-
const optionLabel = getOptionLabel(value, props.keys);
50-
const singleValueDisplay = props.valueDisplay ?? optionLabel;
51-
const showLabelNode = React.isValidElement(singleValueDisplay);
48+
const commonInputProps: SelectInputCommonProperties = {
49+
...pick(props, COMMON_PROPERTIES),
50+
suffixIcon: loading ? <Loading loading size="small" /> : props.suffixIcon,
51+
};
5252

5353
const { classPrefix } = useConfig();
5454
const [inputValue, setInputValue] = useControlled(props, 'inputValue', props.onInputChange);
5555

5656
const inputRef = useRef<InputRef>(null);
5757
const blurTimeoutRef = useRef(null);
5858

59+
const [isTyping, setIsTyping] = useState<boolean>(false);
5960
const [labelWidth, setLabelWidth] = useState<number>(0);
6061

61-
const commonInputProps: SelectInputCommonProperties = {
62-
...pick(props, COMMON_PROPERTIES),
63-
suffixIcon: loading ? <Loading loading size="small" /> : props.suffixIcon,
64-
};
62+
const singleValueDisplay = useMemo(
63+
() => props.valueDisplay ?? getOptionLabel(value, props.keys),
64+
[value, props.valueDisplay, props.keys],
65+
);
66+
67+
const showLabelNode = useMemo(
68+
() => !isTyping && !inputValue && React.isValidElement(singleValueDisplay),
69+
[isTyping, inputValue, singleValueDisplay],
70+
);
6571

6672
const onInnerClear = (context: { e: React.MouseEvent<SVGSVGElement> }) => {
6773
context?.e?.stopPropagation();
@@ -156,7 +162,7 @@ export default function useSingle(props: TdSelectInputProps) {
156162
return (
157163
<Input
158164
ref={inputRef}
159-
// 当 label 为 自定义节点时,input 为空,确保此时 clear icon 可见
165+
// 当 valueDisplay 为 自定义节点时,选中内容时 input 依旧为空,确保此时 clear icon 可见
160166
showClearIconOnEmpty={props.clearable && showLabelNode}
161167
{...commonInputProps}
162168
suffix={
@@ -183,6 +189,14 @@ export default function useSingle(props: TdSelectInputProps) {
183189
// onBlur need to triggered by input when popup panel is null or when popupVisible is forced to false
184190
onBlur={handleBlur}
185191
{...props.inputProps}
192+
onCompositionstart={(v, ctx) => {
193+
setIsTyping(true);
194+
props.inputProps?.onCompositionstart?.(v, ctx);
195+
}}
196+
onCompositionend={(v, ctx) => {
197+
setIsTyping(false);
198+
props.inputProps?.onCompositionend?.(v, ctx);
199+
}}
186200
inputClass={classNames(props.inputProps?.inputClass, {
187201
[`${classPrefix}-input--focused`]: popupVisible,
188202
[`${classPrefix}-is-focused`]: popupVisible,

0 commit comments

Comments
 (0)