Skip to content

Commit 9d409b3

Browse files
authored
fix(Teaxarea): fix value calc error on iOS devices (#601)
1 parent e192d77 commit 9d409b3

File tree

5 files changed

+38
-24
lines changed

5 files changed

+38
-24
lines changed

src/textarea/Textarea.tsx

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,28 +40,29 @@ const Textarea = forwardRef<TextareaRefInterface, TextareaProps>((originProps, r
4040
label,
4141
indicator,
4242
readonly,
43+
onCompositionstart,
44+
onCompositionend,
4345
...otherProps
4446
} = props;
4547

4648
const textareaClass = usePrefixClass('textarea');
4749

4850
const [value, setValue] = useDefault(props.value, defaultValue, props.onChange);
4951
const [textareaStyle, setTextareaStyle] = useState({});
50-
const [composingValue, setComposingValue] = useState<string>('');
5152
const composingRef = useRef(false);
5253
const textareaRef: React.RefObject<HTMLTextAreaElement> = useRef();
5354
const wrapperRef: React.RefObject<HTMLDivElement> = useRef();
5455

5556
const textareaLength = useMemo(() => {
56-
const realValue = composingRef.current ? composingValue : (value ?? '');
57+
const realValue = value ?? '';
5758
if (typeof maxcharacter !== 'undefined') {
5859
const { length = 0 } = getCharacterLength(String(realValue), maxcharacter) as {
5960
length: number;
6061
};
6162
return length;
6263
}
6364
return String(realValue).length || 0;
64-
}, [value, maxcharacter, composingRef, composingValue]);
65+
}, [value, maxcharacter]);
6566

6667
const textareaPropsNames = Object.keys(otherProps).filter((key) => !/^on[A-Z]/.test(key));
6768
const textareaProps = textareaPropsNames.reduce(
@@ -112,32 +113,34 @@ const Textarea = forwardRef<TextareaRefInterface, TextareaProps>((originProps, r
112113

113114
if (value === newStr) return; // 避免在Firefox中重复触发
114115

115-
if (composingRef.current) {
116-
setComposingValue(newStr);
117-
} else {
118-
if (!allowInputOverMax) {
119-
newStr = limitUnicodeMaxLength(newStr, maxlength);
120-
if (maxcharacter && maxcharacter >= 0) {
121-
const stringInfo = getCharacterLength(newStr, maxcharacter);
122-
newStr = typeof stringInfo === 'object' && stringInfo.characters;
123-
}
116+
if (!allowInputOverMax && !composingRef.current) {
117+
newStr = limitUnicodeMaxLength(newStr, maxlength);
118+
if (maxcharacter && maxcharacter >= 0) {
119+
const stringInfo = getCharacterLength(newStr, maxcharacter);
120+
newStr = typeof stringInfo === 'object' && stringInfo.characters;
124121
}
125-
126-
// 中文输入结束,同步 composingValue
127-
setComposingValue(newStr);
128-
setValue(newStr, { e });
129122
}
123+
124+
setValue(newStr, { e });
130125
};
131126

132-
const handleCompositionStart = () => {
127+
const handleCompositionStart = (e: React.CompositionEvent<HTMLTextAreaElement>) => {
133128
composingRef.current = true;
129+
const {
130+
currentTarget: { value },
131+
} = e;
132+
onCompositionstart?.(value, { e });
134133
};
135134

136-
const handleCompositionEnd = (e) => {
135+
const handleCompositionEnd = (e: React.CompositionEvent<HTMLTextAreaElement>) => {
137136
if (composingRef.current) {
138137
composingRef.current = false;
139138
inputValueChangeHandle(e);
140139
}
140+
const {
141+
currentTarget: { value },
142+
} = e;
143+
onCompositionend?.(value, { e });
141144
};
142145

143146
useEffect(() => {
@@ -168,7 +171,7 @@ const Textarea = forwardRef<TextareaRefInterface, TextareaProps>((originProps, r
168171
{...eventProps}
169172
className={textareaInnerClasses}
170173
style={textareaStyle}
171-
value={composingRef.current ? composingValue : value}
174+
value={value}
172175
readOnly={readonly}
173176
autoFocus={autofocus}
174177
disabled={disabled}

src/textarea/defaultProps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ export const textareaDefaultProps: TdTextareaProps = {
1313
indicator: false,
1414
layout: 'horizontal',
1515
placeholder: undefined,
16-
readonly: false,
16+
readonly: undefined,
1717
};

src/textarea/textarea.en-US.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ maxcharacter | Number | - | \- | N
2020
maxlength | Number | - | \- | N
2121
name | String | - | \- | N
2222
placeholder | String | undefined | \- | N
23-
readonly | Boolean | false | \- | N
23+
readonly | Boolean | undefined | \- | N
2424
value | String / Number | - | Typescript:`TextareaValue` `type TextareaValue = string \| number`[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/textarea/type.ts) | N
2525
defaultValue | String / Number | - | uncontrolled property。Typescript:`TextareaValue` `type TextareaValue = string \| number`[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/textarea/type.ts) | N
2626
onBlur | Function | | Typescript:`(value: TextareaValue, context: { e: FocusEvent }) => void`<br/> | N
2727
onChange | Function | | Typescript:`(value: TextareaValue, context?: { e?: InputEvent }) => void`<br/> | N
28+
onCompositionend | Function | | Typescript:`(value: string, context: { e: CompositionEvent }) => void`<br/>trigger on compositionend | N
29+
onCompositionstart | Function | | Typescript:`(value: string, context: { e: CompositionEvent }) => void`<br/>trigger on compositionstart | N
2830
onFocus | Function | | Typescript:`(value: TextareaValue, context : { e: FocusEvent }) => void`<br/> | N

src/textarea/textarea.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ maxcharacter | Number | - | 用户最多可以输入的字符个数,一个中
2020
maxlength | Number | - | 用户最多可以输入的字符个数 | N
2121
name | String | - | 名称,HTML 元素原生属性 | N
2222
placeholder | String | undefined | 占位符 | N
23-
readonly | Boolean | false | 只读状态 | N
23+
readonly | Boolean | undefined | 只读状态 | N
2424
value | String / Number | - | 文本框值。TS 类型:`TextareaValue` `type TextareaValue = string \| number`[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/textarea/type.ts) | N
2525
defaultValue | String / Number | - | 文本框值。非受控属性。TS 类型:`TextareaValue` `type TextareaValue = string \| number`[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/textarea/type.ts) | N
2626
onBlur | Function | | TS 类型:`(value: TextareaValue, context: { e: FocusEvent }) => void`<br/>失去焦点时触发 | N
2727
onChange | Function | | TS 类型:`(value: TextareaValue, context?: { e?: InputEvent }) => void`<br/>输入内容变化时触发 | N
28+
onCompositionend | Function | | TS 类型:`(value: string, context: { e: CompositionEvent }) => void`<br/>中文输入结束时触发 | N
29+
onCompositionstart | Function | | TS 类型:`(value: string, context: { e: CompositionEvent }) => void`<br/>中文输入开始时触发 | N
2830
onFocus | Function | | TS 类型:`(value: TextareaValue, context : { e: FocusEvent }) => void`<br/>获得焦点时触发 | N

src/textarea/type.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* */
66

77
import { TNode } from '../common';
8-
import { FocusEvent, FormEvent } from 'react';
8+
import { FocusEvent, FormEvent, CompositionEvent } from 'react';
99

1010
export interface TdTextareaProps {
1111
/**
@@ -65,7 +65,6 @@ export interface TdTextareaProps {
6565
placeholder?: string;
6666
/**
6767
* 只读状态
68-
* @default false
6968
*/
7069
readonly?: boolean;
7170
/**
@@ -84,6 +83,14 @@ export interface TdTextareaProps {
8483
* 输入内容变化时触发
8584
*/
8685
onChange?: (value: TextareaValue, context?: { e?: FormEvent<HTMLTextAreaElement> }) => void;
86+
/**
87+
* 中文输入结束时触发
88+
*/
89+
onCompositionend?: (value: string, context: { e: CompositionEvent<HTMLTextAreaElement> }) => void;
90+
/**
91+
* 中文输入开始时触发
92+
*/
93+
onCompositionstart?: (value: string, context: { e: CompositionEvent<HTMLTextAreaElement> }) => void;
8794
/**
8895
* 获得焦点时触发
8996
*/

0 commit comments

Comments
 (0)