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

React TypeScript项目中React Beautiful DnD拖拽功能失效求助

React Beautiful DnD拖拽功能无效的修复方案

问题分析

你的代码存在几个核心问题导致拖拽功能失效:

  • 未维护列表项的状态,拖拽结束后无法更新顺序
  • 使用index作为draggableId(反模式,会导致库无法正确追踪拖拽项)
  • DragDropContext未实现拖拽结束后的排序逻辑
  • React列表的key放置位置错误
  • 缺少拖拽占位符(provided.placeholder),会导致布局错乱

修复步骤

1. 为列表添加状态管理与拖拽逻辑

修改List.tsx,用useState维护列表数据,并实现拖拽结束后的排序逻辑:

// List.tsx
import { useState } from "react";
import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd";
import { IconCard } from "./index";
import styles from "../../styles/UI/List.module.css";

export const List = () => {
  const classList = `${styles.list}`;
  // 用useState维护可拖拽的列表数据
  const [items, setItems] = useState([
    { image: { src: "./shopping-cart.png", alt: "" }, title: "one", id: "1" },
    { image: { src: "./shopping-cart.png", alt: "" }, title: "one", id: "2" },
    { image: { src: "./shopping-cart.png", alt: "" }, title: "one", id: "3" },
  ]);

  // 处理拖拽结束后的排序
  const handleDragEnd = (result: DropResult) => {
    if (!result.destination) return; // 拖拽到容器外直接返回

    const newItems = [...items];
    const [movedItem] = newItems.splice(result.source.index, 1);
    newItems.splice(result.destination.index, 0, movedItem);

    setItems(newItems);
  };

  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <Droppable droppableId="list">
        {(provided) => (
          <ul
            className={classList}
            ref={provided.innerRef}
            {...provided.droppableProps}
          >
            {items.map((item, index) => (
              <IconCard
                key={item.id} // 将key放在map返回的元素上
                image={{ src: item.image.src, alt: item.image.alt }}
                title={item.title}
                id={item.id}
                index={index}
                draggableId={item.id} // 传递item的唯一ID作为draggableId
              />
            ))}
            {provided.placeholder} {/* 必须添加,避免拖拽时布局跳动 */}
          </ul>
        )}
      </Droppable>
    </DragDropContext>
  );
};

2. 修复IconCard的Draggable配置

修改IconCard.tsx,使用item的唯一ID作为draggableId,并调整属性位置:

// IconCard.tsx
import styles from "../../styles/UI/Card.module.css";
import { Draggable } from "react-beautiful-dnd";

export const IconCard = ({
  image,
  title,
  text,
  index,
  draggableId,
}: {
  image: { src: string; alt: string };
  title: string;
  text?: string;
  index: number;
  draggableId: string;
}) => {
  return (
    <Draggable draggableId={draggableId} index={index}>
      {(provided) => (
        <div
          className={styles.card}
          {...provided.draggableProps}
          {...provided.dragHandleProps}
          ref={provided.innerRef}
        >
          <div className={styles.imageWrapper}>
            <img src={image.src} alt={image.alt} />
          </div>
          <div>
            <p>{title}</p>
            {text && <p>{text}</p>}
          </div>
        </div>
      )}
    </Draggable>
  );
};

3. 调整App.tsx的结构

移除包裹整个路由的DragDropContext,避免不必要的性能开销:

// App.tsx
import { MyLogin, MyRegistration, RootLayout, Home, Content } from "./pages";
import { createBrowserRouter, RouterProvider } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    children: [
      { index: true, element: <Home /> },
      { path: "/Content", element: <Content /> },
      { path: "/Login", element: <MyLogin /> },
      { path: "/register", element: <MyRegistration /> },
    ],
  },
]);

const App = () => {
  return (
    <main>
      <RouterProvider router={router} />
    </main>
  );
};
export default App;

4. 优化CSS样式

确保拖拽元素有正确的交互提示:

/* Card.module.css */
.card {
  cursor: grab; /* 提示用户可拖拽 */
  user-select: none; /* 防止拖拽时选中文本 */
  /* 保留原有样式... */
}

.card:active {
  cursor: grabbing; /* 拖拽中的光标样式 */
}

关键注意事项

  • 禁止用index作为draggableId,必须使用每个item的唯一标识符
  • 必须实现onDragEnd逻辑更新列表状态,否则拖拽后无视觉变化
  • 不要遗漏provided.placeholder,否则拖拽时会出现布局错乱
  • DragDropContext应仅包裹需要拖拽的区域,而非整个应用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:16:58