fix(练习): 使用nativeEvent.isComposing同步判断输入法状态

- 在InputArea中读取nativeEvent.isComposing同步判断组合状态
- 添加isComposingRef避免状态更新时序问题
- 确保输入法组合期间不触发自动跳转和字符分散

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
ittoview
2026-03-02 01:24:48 +00:00
parent 426a7b0327
commit b4dcd565d6
2 changed files with 18 additions and 5 deletions

View File

@@ -37,13 +37,23 @@ export function InputArea({
}
}, [userInput])
const handleCharInput = (index: number, value: string) => {
const handleCharInput = (
index: number,
e: React.ChangeEvent<HTMLInputElement>
) => {
if (inputLocked) return
const value = e.target.value
const nativeIsComposing =
typeof (e.nativeEvent as InputEvent).isComposing === 'boolean'
? (e.nativeEvent as InputEvent).isComposing
: false
const composing = isComposing || nativeIsComposing
const newInput = [...userInput]
// 输入法组合期间,只更新当前输入框的值,不做任何跳转
if (isComposing) {
if (composing) {
newInput[index] = value
onInputChange(newInput)
return
@@ -125,7 +135,7 @@ export function InputArea({
ref={(el) => (inputRefs.current[index] = el)}
type="text"
value={char}
onChange={(e) => handleCharInput(index, e.target.value)}
onChange={(e) => handleCharInput(index, e)}
onKeyDown={(e) => handleKeyDown(index, e)}
onCompositionStart={onCompositionStart}
onCompositionEnd={onCompositionEnd}

View File

@@ -48,6 +48,7 @@ export default function ProcessPracticePage() {
const [userInput, setUserInput] = useState<string[]>([])
const [charStatuses, setCharStatuses] = useState<CharStatus[]>([])
const [isComposing, setIsComposing] = useState(false)
const isComposingRef = useRef(false)
const [lastErrorTimestamp, setLastErrorTimestamp] = useState<number | null>(
null
)
@@ -198,19 +199,21 @@ export default function ProcessPracticePage() {
latestInputRef.current = newInput
setUserInput(newInput)
if (isComposing) return
if (isComposingRef.current) return
validateInput(newInput)
},
[isComposing, validateInput]
[validateInput]
)
// 输入法状态管理
const handleCompositionStart = useCallback(() => {
isComposingRef.current = true
setIsComposing(true)
}, [])
const handleCompositionEnd = useCallback(() => {
isComposingRef.current = false
setIsComposing(false)
// 输入法确认后,需要将当前输入框中的所有字符分散到后续输入框
requestAnimationFrame(() => {