fix(练习): 使用nativeEvent.isComposing同步判断输入法状态
- 在InputArea中读取nativeEvent.isComposing同步判断组合状态 - 添加isComposingRef避免状态更新时序问题 - 确保输入法组合期间不触发自动跳转和字符分散 via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
@@ -37,13 +37,23 @@ export function InputArea({
|
|||||||
}
|
}
|
||||||
}, [userInput])
|
}, [userInput])
|
||||||
|
|
||||||
const handleCharInput = (index: number, value: string) => {
|
const handleCharInput = (
|
||||||
|
index: number,
|
||||||
|
e: React.ChangeEvent<HTMLInputElement>
|
||||||
|
) => {
|
||||||
if (inputLocked) return
|
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]
|
const newInput = [...userInput]
|
||||||
|
|
||||||
// 输入法组合期间,只更新当前输入框的值,不做任何跳转
|
// 输入法组合期间,只更新当前输入框的值,不做任何跳转
|
||||||
if (isComposing) {
|
if (composing) {
|
||||||
newInput[index] = value
|
newInput[index] = value
|
||||||
onInputChange(newInput)
|
onInputChange(newInput)
|
||||||
return
|
return
|
||||||
@@ -125,7 +135,7 @@ export function InputArea({
|
|||||||
ref={(el) => (inputRefs.current[index] = el)}
|
ref={(el) => (inputRefs.current[index] = el)}
|
||||||
type="text"
|
type="text"
|
||||||
value={char}
|
value={char}
|
||||||
onChange={(e) => handleCharInput(index, e.target.value)}
|
onChange={(e) => handleCharInput(index, e)}
|
||||||
onKeyDown={(e) => handleKeyDown(index, e)}
|
onKeyDown={(e) => handleKeyDown(index, e)}
|
||||||
onCompositionStart={onCompositionStart}
|
onCompositionStart={onCompositionStart}
|
||||||
onCompositionEnd={onCompositionEnd}
|
onCompositionEnd={onCompositionEnd}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export default function ProcessPracticePage() {
|
|||||||
const [userInput, setUserInput] = useState<string[]>([])
|
const [userInput, setUserInput] = useState<string[]>([])
|
||||||
const [charStatuses, setCharStatuses] = useState<CharStatus[]>([])
|
const [charStatuses, setCharStatuses] = useState<CharStatus[]>([])
|
||||||
const [isComposing, setIsComposing] = useState(false)
|
const [isComposing, setIsComposing] = useState(false)
|
||||||
|
const isComposingRef = useRef(false)
|
||||||
const [lastErrorTimestamp, setLastErrorTimestamp] = useState<number | null>(
|
const [lastErrorTimestamp, setLastErrorTimestamp] = useState<number | null>(
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
@@ -198,19 +199,21 @@ export default function ProcessPracticePage() {
|
|||||||
latestInputRef.current = newInput
|
latestInputRef.current = newInput
|
||||||
setUserInput(newInput)
|
setUserInput(newInput)
|
||||||
|
|
||||||
if (isComposing) return
|
if (isComposingRef.current) return
|
||||||
|
|
||||||
validateInput(newInput)
|
validateInput(newInput)
|
||||||
},
|
},
|
||||||
[isComposing, validateInput]
|
[validateInput]
|
||||||
)
|
)
|
||||||
|
|
||||||
// 输入法状态管理
|
// 输入法状态管理
|
||||||
const handleCompositionStart = useCallback(() => {
|
const handleCompositionStart = useCallback(() => {
|
||||||
|
isComposingRef.current = true
|
||||||
setIsComposing(true)
|
setIsComposing(true)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleCompositionEnd = useCallback(() => {
|
const handleCompositionEnd = useCallback(() => {
|
||||||
|
isComposingRef.current = false
|
||||||
setIsComposing(false)
|
setIsComposing(false)
|
||||||
// 输入法确认后,需要将当前输入框中的所有字符分散到后续输入框
|
// 输入法确认后,需要将当前输入框中的所有字符分散到后续输入框
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user