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

使用react-beautiful-dnd拖拽时元素乱跑问题排查

问题诊断与修复方案

核心问题:Portal破坏了react-beautiful-dnd的定位逻辑

你在QuestionCard中针对固定定位的拖拽元素使用Portal,这是导致拖拽乱跑的直接原因。react-beautiful-dnd内部会通过计算拖拽元素在原DOM结构中的位置来实时更新拖拽时的视觉位置,而Portal会将拖拽元素转移到DOM树的其他节点下,打破了原本的位置计算上下文,导致定位坐标错乱。

修复步骤:

  1. 移除Portal相关代码
    直接返回Card组件即可,react-beautiful-dnd会自行处理拖拽元素的层级和定位,不需要手动用Portal包裹:

    const QuestionCard: React.FC<{
        provided: DraggableProvided,
        snapshot: DraggableStateSnapshot,
        question: Question;
    }> = ({ question, provided, snapshot }) => {
        return (
            <Card
                sx={{ mb: 1, position: 'relative', height: 'auto' }}
                ref={provided.innerRef}
                {...provided.draggableProps}
                {...provided.dragHandleProps}
            >
                <CardHeader title={question.name} />
                {/* <Divider /> */}
            </Card>
        );
    };
    
  2. 验证数据源排序的稳定性
    确保orderBy(quiz!.questions, 'position')返回的数组顺序在渲染时是稳定的,避免因排序逻辑导致Draggable的index参数出现异常。如果position字段是唯一且连续的,这个排序逻辑没问题,但如果存在重复值,可能会导致index错乱。

  3. 检查MUI样式干扰
    目前你的Card样式position: relative不会影响拖拽,但需要确保没有其他全局样式或父容器样式(比如transform、overflow)干扰react-beautiful-dnd的定位。如果后续还有问题,可以尝试给Droppable的容器添加position: relative来确保定位上下文正确。

额外注意事项

  • 确保reorder函数的逻辑正确,能正确生成新的排序后的数组,避免拖拽结束后数据源更新错误。
  • 避免在Draggable的index参数中使用不稳定的值,必须基于当前渲染数组的索引,不能用数据源中的position字段代替,因为拖拽过程中数组顺序会动态变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:10:48