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

使用MUI的ListboxComponent时Autocomplete的onChange不触发

Material UI Autocomplete + react-window 虚拟滚动 onChange 失效解决

问题

用Material UI的Autocomplete组件搭配react-window的FixedSizeList自定义ListboxComponent后,onChange事件完全触发不了,给ListItem加onClick也没用。但去掉自定义的ListboxComponent后一切正常,怀疑是ref传递的问题。

原代码

<Autocomplete
  options={options}
  fullWidth
  renderInput={renderOptionValue}
  onChange={(e, value) => {
    // @ts-ignore
    console.log(e.target, value.title);
  }}
  getOptionLabel={(option) => getUserFullName(option)}
  PopperComponent={(props) => <S.DropDownPopper {...props} />}
  ListboxComponent={() => (
    <FixedSizeList
      height={400}
      itemCount={options.length}
      itemData={[...options]}
      itemSize={36}
      overscanCount={5}
      width="100%"
    >
      {(props) => <ListItem {...props} />}
    </FixedSizeList>
  )}
/>

解决方法

核心问题

你没把Autocomplete传给ListboxComponent的关键props(包括ref、事件处理、角色属性等)传递给FixedSizeList,同时自定义的ListItem也没绑定Autocomplete内部的选择逻辑,导致组件无法识别点击/选择动作。

修改步骤

  1. 用forwardRef封装自定义Listbox
    必须把Autocomplete传入的ref传递给FixedSizeList,这样组件才能正确管理焦点和交互。
  2. 复用Autocomplete默认的列表项
    不要自己写ListItem,直接用Autocomplete生成的默认列表项,避免丢失选择逻辑。

修改后完整代码

import { useAutocomplete } from '@mui/material/Autocomplete';
import FixedSizeList from 'react-window/FixedSizeList';
import React from 'react';

// 自定义虚拟滚动列表容器
const CustomListbox = React.forwardRef((props, ref) => {
  const { children, ...restProps } = props;
  const { options } = useAutocomplete();

  return (
    <FixedSizeList
      ref={ref}
      itemCount={options.length}
      itemSize={36}
      height={400}
      width="100%"
      overscanCount={5}
      {...restProps} // 传递Autocomplete的Listbox属性
    >
      {({ index, style }) => {
        // 获取Autocomplete默认生成的对应索引列表项
        const defaultListItem = React.Children.toArray(children)[index];
        // 克隆项并添加虚拟滚动的样式
        return React.cloneElement(defaultListItem, { style });
      }}
    </FixedSizeList>
  );
});

// 使用修改后的Autocomplete
<Autocomplete
  options={options}
  fullWidth
  renderInput={renderOptionValue}
  onChange={(e, value) => {
    // @ts-ignore
    console.log(e.target, value.title);
  }}
  getOptionLabel={(option) => getUserFullName(option)}
  PopperComponent={(props) => <S.DropDownPopper {...props} />}
  ListboxComponent={CustomListbox} // 替换为自定义容器
/>

说明

  • 传递restProps给FixedSizeList,确保Autocomplete的键盘导航、焦点管理等逻辑正常工作。
  • 复用默认列表项,自动带上了Autocomplete的点击选择逻辑,无需手动绑定onClick。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:30:24