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

React beautiful DND报错Unable to find draggable with id问题求助

问题根因

react-beautiful-dnd强制要求所有<Draggable>组件的draggableId属性全局唯一。你的实现中,同一个任务同时出现在「全任务列」和「已选任务列」时,会渲染两个使用相同draggableId的拖拽元素,触发库内部的注册冲突:删除已选列的任务时,库会把对应id的拖拽记录从内部注册表移除,全任务列中同id的元素就会丢失注册信息,再次拖拽就会抛出Unable to find draggable with id: xxx错误。

修复方案

方案1:允许已选任务拖拽排序(完全满足默认需求)

修改1:调整task.jsx的拖拽id逻辑

给已选列的拖拽id加唯一前缀,保证全局id不重复:

// task.jsx 中<Draggable>组件的draggableId修改为:
<Draggable
  draggableId={this.props.isSelectedTasksColumn ? `selected-${this.props.task.id}` : this.props.task.id}
  index={this.props.index}
  isDragDisabled={isDragDisabled}
>

修改2:调整App.jsx的拖拽结束逻辑

统一处理拖拽id的前缀,拿到原始任务id后再操作数据:

// App.jsx的onDragEnd方法开头,新增原始id提取逻辑
onDragEnd = result => {
  this.setState({
    homeIndex: null,
  });

  const { destination, source, draggableId } = result;
  // 新增:提取原始任务id,去掉已选任务的前缀
  const rawTaskId = draggableId.replace(/^selected-/, '');

  if (!destination) {
    return;
  }

  if (
    destination.droppableId === source.droppableId &&
    destination.index === source.index
  ) {
    return;
  }

  const home = this.state.columns[source.droppableId];
  const foreign = this.state.columns[destination.droppableId];

  if (home === foreign) {
    const newTaskIds = Array.from(home.taskIds);
    // 替换draggableId为rawTaskId
    newTaskIds.splice(source.index, 1);
    newTaskIds.splice(destination.index, 0, rawTaskId);

    const newHome = {
      ...home,
      taskIds: newTaskIds,
    };

    const newState = {
      ...this.state,
      columns: {
        ...this.state.columns,
        [newHome.id]: newHome,
      },
    };

    this.setState(newState);
    return;
  }

  const foreignTaskIds = Array.from(foreign.taskIds);
  // 替换draggableId为rawTaskId
  foreignTaskIds.splice(destination.index, 0, rawTaskId);
  const newForeign = {
    ...foreign,
    taskIds: foreignTaskIds,
  };

  const newState = {
    ...this.state,
    columns: {
      ...this.state.columns,
      [newForeign.id]: newForeign,
    },
  };
  this.setState(newState);
};

方案2:禁止已选任务拖拽(代码改动更小)

如果你的需求不需要支持已选列内部的任务拖拽排序,可以直接禁用已选任务的拖拽能力,从根源避免id冲突:

// task.jsx中修改isDragDisabled的赋值逻辑
const isDragDisabled = this.props.isSelectedTasksColumn;

已选列的任务不会被注册为可拖拽元素,不会触发id重复问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:24:06