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

React Beautiful Drag and Drop拖拽失效,请求排查代码问题

问题排查:react-beautiful-dnd 拖拽异常

问题描述

使用 react-beautiful-dnd 编写拖拽列表时,拖拽列表项出现元素位置错乱、重复显示的异常(拖拽元素时原位置元素未消失,拖拽元素出现偏移),代码及问题如下:

原代码

import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";

const Column = () => {
  const itemList = [
    { id: "1", task: "Pierwszy element" },
    { id: "2", task: "Drugi element" },
    { id: "3", task: "Trzeci element" },
    { id: "4", task: "Czwarty element" },
    { id: "5", task: "Piąty element" },
    { id: "6", task: "Szósty element" },
  ];

  return (
    <DragDropContext>
      <div className="border-4 border-base-300 bg-base-300 mx-auto mt-2 w-[500px] rounded-md font-sans">
        <h1 className="text-center p-1 text-lg font-bold">
          Drag and drop list
        </h1>
        <Droppable droppableId="characters">
          {(provided) => (
            <ul
              className="bg-base-300 characters"
              {...provided.droppableProps}
              ref={provided.innerRef}
            >
              {itemList.map((item, index) => {
                return (
                  <Draggable key={item.id} draggableId={item.id} index={index}>
                    {(provided) => (
                      <li
                        ref={provided.innerRef}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        className="font-sans p-3 text-[15px] my-2 last:my-0 bg-base-200"
                      >
                        {item.task}
                      </li>
                    )}
                  </Draggable>
                );
              })}
              {provided.placeholder}
            </ul>
          )}
        </Droppable>
      </div>
    </DragDropContext>
  );
};

export default Column;

错误原因及修复方案

1. 缺少 DragDropContext 的 onDragEnd 回调

react-beautiful-dnd 强制要求为 DragDropContext 提供 onDragEnd 函数,这是库处理拖拽结束后状态重置、位置修正的核心入口。没有该回调,库无法正确处理拖拽后的视图逻辑,直接导致视觉错乱。

2. 列表数据未做响应式管理

原代码中 itemList 是静态常量,拖拽排序后无法触发组件重新渲染,视图不会更新。需要用 useState 将其转为响应式状态,确保排序后列表能实时刷新。

修复后的代码

import { useState } from "react";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";

const Column = () => {
  // 用 useState 管理列表数据,实现响应式更新
  const [itemList, setItemList] = useState([
    { id: "1", task: "Pierwszy element" },
    { id: "2", task: "Drugi element" },
    { id: "3", task: "Trzeci element" },
    { id: "4", task: "Czwarty element" },
    { id: "5", task: "Piąty element" },
    { id: "6", task: "Szósty element" },
  ]);

  // 处理拖拽结束逻辑,完成列表排序
  const handleDragEnd = (result) => {
    // 若拖拽未完成(如拖到容器外),直接终止
    if (!result.destination) return;

    const items = Array.from(itemList);
    // 移除原位置元素
    const [reorderedItem] = items.splice(result.source.index, 1);
    // 将元素插入目标位置
    items.splice(result.destination.index, 0, reorderedItem);

    setItemList(items);
  };

  return (
    // 添加上必填的 onDragEnd 回调
    <DragDropContext onDragEnd={handleDragEnd}>
      <div className="border-4 border-base-300 bg-base-300 mx-auto mt-2 w-[500px] rounded-md font-sans">
        <h1 className="text-center p-1 text-lg font-bold">
          Drag and drop list
        </h1>
        <Droppable droppableId="characters">
          {(provided) => (
            <ul
              className="bg-base-300 characters"
              {...provided.droppableProps}
              ref={provided.innerRef}
            >
              {itemList.map((item, index) => {
                return (
                  <Draggable key={item.id} draggableId={item.id} index={index}>
                    {(provided) => (
                      <li
                        ref={provided.innerRef}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        className="font-sans p-3 text-[15px] my-2 last:my-0 bg-base-200"
                      >
                        {item.task}
                      </li>
                    )}
                  </Draggable>
                );
              })}
              {provided.placeholder}
            </ul>
          )}
        </Droppable>
      </div>
    </DragDropContext>
  );
};

export default Column;

额外说明

  • handleDragEnd 中的数组操作是 react-beautiful-dnd 的标准排序流程,通过复制原数组、剪切粘贴元素的方式避免直接修改原状态。
  • 确保 draggableId 和组件 key 使用唯一稳定的标识(此处用 item.id 是正确的),不要用 index 作为 key,否则排序后可能出现组件复用异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:23:23