React DnD示例项目运行方法及拖拽排序功能失效问题求助
如何运行React DnD示例项目
- 克隆React DnD官方仓库:
git clone https://github.com/react-dnd/react-dnd.git - 进入仓库根目录:
cd react-dnd - 安装项目依赖:
npm install(也可使用pnpm或yarn) - 切换到examples目录下的目标示例文件夹,比如
examples/ts/kanban - 启动示例项目:
npm start
自有项目拖拽排序功能问题排查
你的代码只实现了拖拽源(useDrag),但完全缺失**放置目标(useDrop)**的逻辑——元素能被拖拽,但没有可接受放置的区域,也没有处理排序的逻辑,自然无法正常工作。要实现拖拽排序,每个元素需要同时具备拖拽和放置能力,并且在放置时更新数组顺序。
修改后的完整代码如下:
import React from "react"; import { DndProvider, useDrag, useDrop } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; export default function Test() { const [data, setData] = React.useState(["A", "B", "C", "D"]); // 处理元素位置交换的核心函数 const moveItem = (dragIndex: number, hoverIndex: number) => { const dragItem = data[dragIndex]; const newData = [...data]; newData.splice(dragIndex, 1); newData.splice(hoverIndex, 0, dragItem); setData(newData); }; return ( <DndProvider backend={HTML5Backend}> {data.map((item, index) => ( <ShowItem key={item} item={item} index={index} moveItem={moveItem} /> ))} </DndProvider> ); } const ShowItem = ({ item, index, moveItem }: { item: string; index: number; moveItem: (dragIndex: number, hoverIndex: number) => void }) => { // 拖拽源逻辑 const [{ isDragging }, dragRef] = useDrag( () => ({ type: "CARD", item: { index }, // 传递当前元素索引,用于后续位置计算 collect: (monitor) => ({ isDragging: !!monitor.isDragging(), }), }), [index] ); // 放置目标逻辑 const [, dropRef] = useDrop( () => ({ accept: "CARD", hover(item: { index: number }) { const dragIndex = item.index; const hoverIndex = index; // 拖拽自身时不处理 if (dragIndex === hoverIndex) return; // 触发位置交换 moveItem(dragIndex, hoverIndex); // 更新拖拽元素的索引(数组顺序变化后同步) item.index = hoverIndex; }, }), [index, moveItem] ); // 合并拖拽和放置的ref,让元素同时支持两种能力 const ref = React.useRef<HTMLDivElement>(null); React.useImperativeHandle(dragRef, () => ref.current); React.useImperativeHandle(dropRef, () => ref.current); return ( <div ref={ref} style={{ width: "100px", height: "100px", background: "white", margin: "10px", opacity: isDragging ? 0.5 : 1, cursor: "grab", border: "1px solid #ccc" }} > {item} </div> ); };
关键修改点:
- 添加
useDrop钩子,让每个ShowItem成为可放置目标 - 新增
moveItem函数,负责修改数组顺序实现排序 - 拖拽时传递元素索引,放置时通过
hover事件触发位置交换 - 合并拖拽和放置的ref,确保同一个元素同时支持拖拽与放置
内容的提问来源于stack exchange,提问作者Amin Soraya
相关产品推荐
相关产品推荐

