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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 15:58:08