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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:54:50