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

React DnD拖动外部同名物品未生成新key问题排查求助

问题根因

你第一次拖拽外部组件进入看板时,直接修改了原始的外部组件对象,给它新增了key属性。由于外部组件的component是引用类型,后续再拖拽同一组件时,它已经携带key属性,因此会命中移动逻辑而非新增逻辑。

修复步骤

1. 核心修复:避免修改原始拖拽对象

修改Board组件drop回调中的对象合并逻辑,不要直接修改传入的item,而是创建全新的对象存储到看板状态中:

// 原来的写法(错误:会修改原对象)
// const newItem = Object.assign(item, itemKey);
// 修复后的写法
const newItem = Object.assign({}, item, itemKey);

将空对象作为Object.assign的第一个参数,就会生成完全独立的新对象,不会污染原始的外部组件对象,后续拖拽同一外部组件时item.key依旧为undefined,会正常触发新增逻辑。

2. 可选优化:增加拖拽来源标识(更稳妥)

仅靠key是否存在判断逻辑有潜在风险,你可以给不同来源的拖拽对象增加标识字段,判断更准确:

修改外部Component组件的useDrag配置:

useDrag(
  () => ({
    type: ItemTypes.COMPONENT,
    item: {
      ...component,
      source: 'external' // 标记为外部来源
    },
  }),
  []
)

修改看板内Item组件的useDrag配置:

useDrag(
  () => ({
    type: ItemTypes.COMPONENT,
    item: {
      ...component,
      source: 'internal' // 标记为内部来源
    },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  }),
  [component.key, left, top] // 修复依赖项:React的key属性不会传递给子组件props,改用component.key
)

调整Board组件的drop判断逻辑:

drop: (item) => {
  console.log(item.name, item.key);
  if (item.source === 'external') {
    const { nanoid } = require("nanoid");
    const itemKey = { key: nanoid(16) };
    const newItem = Object.assign({}, item, itemKey);
    setComponents((components) => [...components, newItem]);
    console.log("add");
  } else {
    // 这里补充内部拖拽的移动逻辑即可
    console.log("moving");
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:36:00