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

在react-virtualized List中使用react-beautiful-dnd出现拖拽报错

解决react-virtualized List与react-beautiful-dnd拖拽时"Cannot find droppable entry with id"错误

问题根源

react-virtualized的List组件会动态卸载视口外的行(即你的Section对应的Droppable组件),而react-beautiful-dnd要求所有可能的目标Droppable必须始终存在于DOM中,才能在拖拽过程中追踪目标区域。当你拖拽元素到一个已被卸载的Section位置时,就会触发找不到droppable id的报错。

解决方案

方法1:拖拽时临时禁用虚拟列表的DOM卸载

通过状态控制,在拖拽过程中强制所有Section保持挂载,确保react-beautiful-dnd能定位到所有目标Droppable,拖拽结束后恢复虚拟列表的正常渲染:

  1. 添加拖拽状态管理:
import { useState } from 'react';

const [isDragging, setIsDragging] = useState(false);

const onDragStart = () => {
  setIsDragging(true);
};

const onDragEnd = (result) => {
  setIsDragging(false);
  // 原有拖拽结束逻辑(如更新sections数组)
};
  1. 修改List组件配置:
<List
  autoHeight={!isDragging}
  // 拖拽时设置足够大的高度,让所有Section都显示(可根据实际Section高度调整数值)
  height={isDragging ? state.sections.length * 200 : height}
  width={width}
  rowCount={state.sections.length}
  rowHeight={cache.rowHeight}
  deferredMeasurementCache={cache}
  rowRenderer={rowRenderer}
  scrollTop={scrollTop}
  // 拖拽时预渲染所有行,避免视口外Section被卸载
  overscanRowCount={isDragging ? state.sections.length : 10}
/>
  1. 更新DragDropContext的回调:
<DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>

方法2:将Droppable提升至虚拟列表外层,自定义分组拖拽逻辑

放弃每个Section作为独立Droppable,改为整个List作为单一Droppable,通过坐标计算判断拖拽目标Section,彻底规避虚拟列表DOM卸载的冲突:

  1. 调整组件结构:
<DragDropContext onDragEnd={onDragEnd}>
  <WindowScroller>
    {({ height, scrollTop }) => (
      <AutoSizer disableHeight>
        {({ width }) => (
          <Droppable droppableId="all-sections">
            {(provided) => (
              <div ref={provided.innerRef} {...provided.droppableProps}>
                <List
                  autoHeight
                  height={height}
                  width={width}
                  rowCount={state.sections.length}
                  rowHeight={cache.rowHeight}
                  deferredMeasurementCache={cache}
                  rowRenderer={rowRenderer}
                  scrollTop={scrollTop}
                />
                {provided.placeholder}
              </div>
            )}
          </Droppable>
        )}
      </AutoSizer>
    )}
  </WindowScroller>
</DragDropContext>
  1. 自定义拖拽目标判断逻辑:
    在onDragEnd中,通过拖拽结束的坐标,结合每个Section的位置信息,计算出目标Section,再更新sections数组完成元素迁移。这种方式需要额外处理DOM坐标获取,但能完美兼容虚拟列表的动态渲染特性。

方法3:使用第三方兼容库

使用react-beautiful-dnd-virtualized这类专门解决两者兼容问题的库,它会自动处理拖拽过程中虚拟列表的行渲染策略,确保目标Droppable始终存在于DOM中,无需手动修改虚拟列表配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:44:59