You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React嵌套输入组件在Android GBoard输入时出现内容重复问题

GBoard输入"@"时受控组件内容重复的问题

组件代码

const Child = ({ onChange, value }) => {
  const [localValue, setLocalValue] = useState("");

  useEffect(() => {
    setLocalValue(value);
  }, [value]);

  return <input onChange={onChange} value={localValue} />;
};

const Parent = () => {
  const [value, setValue] = useState("");

  const handleChange = (e) => setValue(e.target.value);

  return <Child onChange={handleChange} value={value} />;
};

组件说明

该子组件为受控输入组件,会先将父组件传入的value存入本地状态localValue,再将localValue绑定到输入框的value属性进行渲染。

问题现象

  • 桌面Chrome环境下输入表现正常,内容可正常显示
  • 使用Android GBoard(版本12.2.05.469624536-release-arm64-v8)输入时,输入"@"字符后内容会重复:例如输入"test"无异常,但输入"test@"会立即变为"testtest@",有时会变成"test@test@"
  • 此问题仅在输入"@"后出现,且不会在其他安卓键盘上发生

能否复现?

能复现该问题,在指定场景与GBoard版本下可稳定触发。

原因解释

问题核心在于GBoard输入"@"的特殊事件逻辑,与子组件冗余的本地状态更新机制冲突:

  1. GBoard输入"@"时会触发两次onChange事件:第一次传递插入"@"前的文本(如"test"),第二次传递插入"@"后的完整文本(如"test@")
  2. 子组件通过useEffect异步同步父组件value到本地localValue,当第一次onChange触发父状态更新后,useEffect还未执行,第二次onChange又触发父状态更新,导致两次useEffect的执行顺序与事件触发顺序出现错位
  3. 叠加GBoard对输入框值的重复读取逻辑,最终造成文本拼接重复;另外,子组件额外维护本地状态的设计本身违背了受控组件的原则,这是状态不同步的根源。

解决方案

移除子组件的本地状态,让输入框直接绑定父组件传入的value,回归标准受控组件实现:

const Child = ({ onChange, value }) => {
  return <input onChange={onChange} value={value} />;
};

const Parent = () => {
  const [value, setValue] = useState("");

  const handleChange = (e) => setValue(e.target.value);

  return <Child onChange={handleChange} value={value} />;
};

该方案既符合React受控组件的设计规范,也从根源上避免了状态不同步导致的重复问题。

内容的提问来源于stack exchange,提问作者Edwin Tandiono

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:35:28