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

Material UI Autocomplete自定义Paper内输入框每输入一个字符失焦问题求解

问题根因

你当前遇到的输入框失焦问题核心原因是:你在Autocomplete的props中内联定义了PaperComponent函数。
每当你更新options、customFilterString等状态触发父组件重渲染时,这个内联定义的PaperComponent会生成全新的函数引用,React会判定这是一个全新的组件类型,直接卸载旧的Paper实例并重新挂载新实例,内部的自定义输入框也会随之销毁重建,自然就会丢失焦点。


可行解决方案

方案1:稳定PaperComponent的引用

不要内联定义PaperComponent,根据你的使用场景可以二选一:

  • 如果自定义Paper不需要用到Autocomplete所在组件的内部状态,直接把PaperComponent定义移到组件外部,全局只声明一次即可。
  • 如果需要用到内部状态(比如customFilterString、closeOptionsList等),用useMemo包裹PaperComponent的定义,保证仅在依赖项变化时才更新引用:
// 在Autocomplete所在的组件内部声明
const MemoizedPaperComponent = useMemo(() => {
  return ({children, ...other}) => (
    <Paper {...other}>
      <ClickAwayListener onClickAway={closeOptionsList}>
        <div key="click-away-wrapper">
          <Input
            styleInput={{width: '100%'}}
            value={customFilterString}
            onChange={handleCustomFilterChange}
            className="slds-m-horizontal_small slds-m-top_small"
            iconRight={<InputIcon name="search" category="utility" />}
          />
          {children}
        </div>
      </ClickAwayListener>
    </Paper>
  )
// 依赖项仅包含你用到的内部变量即可
}, [closeOptionsList, customFilterString, handleCustomFilterChange])

// Autocomplete props处引用
<Autocomplete
  PaperComponent={MemoizedPaperComponent}
  // 其他props保持不变
/>

方案2:调整搜索框放置位置

如果不想修改Paper的定义,也可以换更符合MUI Autocomplete渲染逻辑的放置位置:

  • 用ListboxComponent属性自定义选项列表容器,把搜索框放在选项列表的顶部
  • 或者自定义PopperComponent,把搜索框嵌入到弹出层的最上方,完全避开Paper的重渲染逻辑影响

额外排查点

检查ClickAwayListener的onClickAway逻辑,避免输入框输入时误触发关闭逻辑,也可能连带导致焦点丢失。可以在关闭前增加判断,仅当点击源不在输入框和选项列表内部时再执行关闭。


内容的提问来源于stack exchange,提问作者Tyler Dahle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:36:01