Material UI Autocomplete集成react-virtuoso虚拟滚动向上导航异常问题
问题根因
- MUI Autocomplete 默认的键盘导航逻辑只会操作原生下拉列表的滚动偏移,不会同步触发react-virtuoso的滚动定位。当你按向上键选中超出可视区上方的选项时,Autocomplete内部的高亮索引已经更新,但react-virtuoso不知道需要滚动到对应索引的位置,就会出现「逻辑上选中了上方不可见选项,但视图没有滚动」的问题,后续按向下键时需要先把之前多按的向上次数抵消,才能回到可视区的选项。
- 另外Autocomplete默认会给下拉列表添加固定最大高度和overflow滚动属性,和react-virtuoso的滚动容器冲突,也是滚动同步失效的常见诱因。
修复步骤
1. 关闭Autocomplete默认的列表滚动行为
将Autocomplete默认列表的滚动权限完全交给react-virtuoso,避免双滚动容器冲突:
<Autocomplete {/* 其他原有配置项 */} ListboxProps={{ style: { maxHeight: 'none', overflow: 'hidden', padding: 0 } }} />
2. 同步高亮索引与virtuoso滚动位置
通过ref获取react-virtuoso实例,监听Autocomplete的高亮变化事件,主动触发虚拟列表滚动到对应位置:
import { useRef } from 'react'; import { Virtuoso } from 'react-virtuoso'; import Autocomplete from '@mui/material/Autocomplete'; // 组件内部定义virtuoso实例ref const virtuosoRef = useRef<any>(null); // Autocomplete完整配置示例 <Autocomplete options={yourOptionsArray} onHighlightChange={(_, option, reason) => { // 仅响应键盘触发的高亮变更 if (reason === 'keyboard' && option) { // 计算当前高亮选项在完整数组中的索引 const currentIndex = yourOptionsArray.findIndex(item => item.value === option.value); if (currentIndex > -1 && virtuosoRef.current) { // 调用virtuoso的滚动方法 virtuosoRef.current.scrollToIndex({ index: currentIndex, align: 'start' }); } } }} renderList={(listProps) => ( <Virtuoso ref={virtuosoRef} style={{ height: '400px' }} // 可自定义下拉框高度 data={yourOptionsArray} itemContent={(index, item) => ( <li {...listProps.getItemProps({ index, item })}> {item.label} </li> )} /> )} {/* 其他原有配置项 */} />
3. 边界场景兼容
如果你的选项是懒加载动态获取的,可以给Virtuoso添加followOutput="auto"属性,避免主动滚动和用户手动滚动的行为冲突,同时要注意等选项数据加载完成后再执行scrollToIndex逻辑,避免索引匹配错误。
内容的提问来源于stack exchange,提问作者Mbrevda
相关产品推荐
相关产品推荐

