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

React+TypeScript中react-beautiful-dnd拖拽失效问题求助

react-beautiful-dnd 跨列表拖拽失效修复方案

1. 优先排查React严格模式兼容问题

react-beautiful-dnd 未适配 React 18 严格模式,如果项目入口文件(main.jsx/tsx/index.jsx/tsx)中根组件被<StrictMode>包裹,拖拽功能会直接完全失效,且控制台无明确报错。
修复方式:移除根组件外层的<StrictMode>包裹即可,这是该类问题最高发的诱因。

2. 校验DragDropContext的onDragEnd回调逻辑

跨双列表拖拽必须在onDragEnd回调中同步处理两个列表的状态更新,逻辑缺失或错误会直接导致拖拽无响应。可直接参考如下可运行的逻辑实现:

const onDragEnd = (result) => {
  const { source, destination } = result;
  // 拖拽到容器外,直接终止逻辑
  if (!destination) return;
  // 同列表同位置拖拽无变化,直接终止逻辑
  if (
    source.droppableId === destination.droppableId &&
    source.index === destination.index
  ) return;

  // 拷贝两份列表状态避免直接修改原状态
  const activeList = [...todos];
  const completedList = [...completedTodos];
  let draggedItem;

  // 从源拖拽列表移除被拖动的任务项
  if (source.droppableId === "TodosList") {
    draggedItem = activeList.splice(source.index, 1)[0];
  } else {
    draggedItem = completedList.splice(source.index, 1)[0];
  }

  // 将任务项插入到目标列表的指定位置,同步更新任务完成状态
  if (destination.droppableId === "TodosList") {
    draggedItem.isDone = false;
    activeList.splice(destination.index, 0, draggedItem);
  } else {
    draggedItem.isDone = true;
    completedList.splice(destination.index, 0, draggedItem);
  }

  // 批量更新两个列表的状态
  setTodos(activeList);
  setCompletedTodos(completedList);
};

写完回调后记得将其传入DragDropContext组件:<DragDropContext onDragEnd={onDragEnd}>

3. 校验Draggable全局ID唯一性

你在SingleTodo组件中配置的draggableId={todo.id.toString()},必须保证进行中、已完成两个列表内所有任务的id全局唯一,若两个列表存在重复id的项,拖拽功能会直接失效。

4. 现有传参逻辑优化

你在已完成任务列表渲染SingleTodo时,传入的setTodos={setCompletedTodos}虽然不影响拖拽基础运行,但参数名和实际传入的setter不匹配,容易引发后续状态更新逻辑的bug,建议调整SingleTodo的props定义,区分两个列表的setter,保持参数语义一致。

你当前贴出的TodoList、SingleTodo组件中,Droppable和Draggable的ref绑定、props透传、placeholder占位的写法都是正确的,这部分不需要修改。


内容的提问来源于stack exchange,提问作者Ruba Khalil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:09:49