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
相关产品推荐
相关产品推荐

