React中这种useState用法导致无法输入中文的原因是什么?
问题触发原因
核心本质
该问题是受控组件的异步状态更新打断了输入法的合成(Composition)会话导致的。
输入法输入中文的正常流程
使用中文输入法输入时,会经历三个阶段:
- 触发
compositionstart:进入拼音输入的合成状态,此时用户输入的拼音属于中间态,还未选中最终要输入的汉字 - 合成中:用户敲拼音、筛选候选词的过程中,input的
onChange事件会持续触发,但返回的是拼音的中间值 - 触发
compositionend:用户选中汉字后,合成结束,此时input返回最终的中文值
React本身对受控输入框的合成过程做了兼容处理,如果是同步更新绑定的value值,不会打断合成流程。
代码中的问题点
你的状态更新逻辑多了一层异步跳转,刚好打破了React的兼容逻辑:
const App: React.FC = () => { const [a, setA] = useState(''); const [b, setB] = useState(''); useEffect(() => { setA(b); }, [b]); return ( <div className="container"> <input type="text" value={a} onChange={e => { setB(e.target.value); }} /> </div> ); };
- input绑定的value是状态
a,但输入触发onChange时,先同步更新的是状态b a的更新依赖useEffect监听b的变化,而useEffect的执行是在渲染完成后的微任务阶段,属于异步更新- 当你还在拼音输入的合成过程中,第一次渲染用的
a还是旧值,等到useEffect执行setA触发第二次重渲染时,会强制更新input的value,系统会判定输入框的值被主动修改,直接终止正在进行的合成会话,所以你还没选完汉字,拼音就直接被填入输入框,无法正常输入中文。
复现效果

内容的提问来源于stack exchange,提问作者Z_o
相关产品推荐
相关产品推荐

