在Shadcn UI多选下拉框中集成react-window后,搜索过滤时滚动功能失效的问题排查
在Shadcn UI多选下拉框中集成react-window后,搜索过滤时滚动功能失效的问题排查
我帮你排查了代码里的问题,主要有两个关键原因导致搜索过滤后滚动失效,咱们一步步来修复:
1. React-Window 未感知数据源变化,未重新计算滚动区域
React-Window 的 List 组件会缓存滚动相关的状态,当你通过搜索过滤更新 filteredOptions 后,如果没有触发 List 的重新渲染,它会继续使用之前的滚动计算逻辑(基于原来的列表长度),导致滚动条行为异常。
修复方案:给 List 组件添加一个依赖于过滤后列表长度的 key,这样每次列表长度变化时,List 会重新初始化,计算正确的滚动区域:
<List key={filteredOptions.length} // 添加这个key,触发重新渲染 height={200} itemCount={filteredOptions.length} itemSize={32} width="100%" itemData={filteredOptions} > {Row} </List>
2. 嵌套滚动容器导致事件冲突
你在 List 外层套了一个带有 overflow-y-auto 和 max-h-[200px] 的 div,而 React-Window 的 List 本身已经会创建一个固定高度的滚动容器。这种嵌套滚动会导致滚动事件被外层容器拦截,内层的虚拟列表无法正确响应滚动操作。
修复方案:移除外层的滚动容器,让 List 自己负责滚动逻辑:
<CommandGroup> {/* 去掉外层的div,直接渲染List */} <List key={filteredOptions.length} height={200} itemCount={filteredOptions.length} itemSize={32} width="100%" itemData={filteredOptions} > {Row} </List> </CommandGroup>
额外优化建议
如果你担心“全选”按钮被滚动遮挡,可以把它放在 CommandList 里的独立区域,保持 sticky 定位的同时,调整虚拟列表的高度给按钮留出空间:
<CommandList> <CommandEmpty>No options found.</CommandEmpty> {filteredOptions.length ? ( <div className="sticky top-0 bg-white z-10 font-bold flex gap-2 h-[26px] items-center mx-3 my-0 pt-[6px] text-sm"> <Checkbox checked={allSelected} onClick={toggleSelectAll} /> Select all </div> ) : null} <CommandGroup> <List key={filteredOptions.length} height={174} // 调整高度,给全选按钮留出空间(200-26=174) itemCount={filteredOptions.length} itemSize={32} width="100%" itemData={filteredOptions} > {Row} </List> </CommandGroup> </CommandList>
这样修改后,搜索过滤时虚拟列表会正确重新计算滚动区域,滚动功能就能正常工作啦。
备注:内容来源于stack exchange,提问作者Hardik Aswal
相关产品推荐
相关产品推荐

