【问题标题】:Key is null even after being assigned a value即使在被分配了一个值之后,键也是空的
【发布时间】:2019-06-26 14:13:45
【问题描述】:

这是我第一次尝试 React。我正在尝试构建一个 UI,我可以在其中拖放图像并移动它们的顺序。我意识到首先,这将要求每个图像都有一个唯一的密钥,但我找不到正确的方法。我不明白为什么,即使我明确分配了一个键,当我在控制台上查看对象时它仍然为空。我试过了:

<div>
  {this.props.imageArray.map((image, index) => (
    <span
      key={index}
    >
      {image}
    </span>
  ))}
</div>;

这仍然给了我null 的键(我也尝试为外部 div 分配它自己的键,但这也不起作用)。

我已经读过,如果未指定 key,它默认为数组中元素的 id(当未指定 key 但这是预期时,我仍然得到一个空值),所以我尝试手动分配它

<div>
  {this.props.imageArray.map(image => (
    <span key={this.props.images.length}>{image}</span>
  ))}
</div>;

但这给了我这个错误:

警告:遇到两个孩子使用相同的密钥,2。键应该是唯一的,以便组件在更新时保持其身份......

即使# 随着每个错误的增加而增加,该错误也会随着添加到数组中的每个新图像而继续存在。这告诉我密钥正在增加,但由于某种原因,它仍然不是唯一的。我的猜测是每次都以某种方式创建了 2 个孩子?无论如何,这给了我错误的输出,所以我不能使用它。

我也简单地尝试过这个,它给了我正确的输出,但我得到了与上面相同的警告,除了 # 它说 [object Object]

<div>
  {this.props.imageArray.map(image => (
    <span key={image}>{image}</span>
  ))}
</div>;

这是我完整的组件代码。当我在图像周围移动时检查拖动事件中的对象 ID 时,它始终是未定义的。我只需要弄清楚这个独特的关键问题是怎么回事,但是如果您发现拖放功能有任何问题,我也可以使用一些指针。

class Images extends Component {
    state = {
      arrayOfImages: [...this.props.imageArray],
      droppedImage: []
    };

    onDragStart = (ev, id) => {
      ev.dataTransfer.setData("id", id);
    };

    onDrop = ev => {
      let id = ev.dataTransfer.getData("id");
      let draggedImage = this.state.arrayOfImages.filter(function(image) {
        return image === id;
      });

      this.setState({
        droppedImage: draggedImage
      });
    };
    onDragOver = ev => {
      ev.preventDefault();
    };

    render() {
      return (
        <React.Fragment>
          <div>
            {this.props.imageArray.map((image, index) => (
              <span
                key={index}
                onDragStart={this.onDragStart}
                draggable //I know this isn't necessary for images
              >
                {image}
              </span>
            ))}
          </div>
          <div
            className="dropTarget"
            onDragOver={e => this.onDragOver(e)}
            onDrop={e => this.onDrop(e)}
          >
            {this.state.droppedImage}
          </div>
        </React.Fragment>
      );
    }
  }

  export default Images;

【问题讨论】:

  • 你在这里和那里提到“我读过......”和“它说......”。你在关注/指的是什么?
  • Randy,我一直在寻找类似的 stackoverflow 帖子和 React 文档
  • 你能把这个配对一下吗?当您使用索引作为键时,有什么问题?使用长度作为键永远不会起作用,对象也是如此。
  • Kyle,当我使用索引作为键时,我得到每个对象中键的空值,并且每个拖放事件传递的 id 未定义
  • 您在哪里尝试读取密钥,您是否遇到错误?

标签: javascript reactjs drag-and-drop key


【解决方案1】:

这是一个工作示例,它用整数数组代替图像数组。我会将图像部分留给您,因为在您的示例中这似乎不完整。您的解决方案的核心部分位于名为“images.js”的文件中。

https://codesandbox.io/s/013jrvn2pp

您的代码只有几个问题:

  1. 正如@Kyle 正确指出的那样,您需要为您的 丢弃的元素。最容易使用的索引是id 财产。
<span   
   key={index}   
    id={index} 
>
  1. dragStart 事件的处理程序与来自事件 API 的函数签名不匹配。这意味着您必须从处理程序中的事件对象派生id 属性值(我已经在提供的解决方案中完成了):
onDragStart = (ev, id) => {
 ... 
};
Must be:
onDragStart = (ev) => {
 ...
};
  1. 您还错误地使用了.dataTransfer() 方法。 setData() API 需要数据类型作为第一个参数,值作为第二个参数。 getData() API 只需要数据类型。

如果您尝试通过id(也是数组索引)来操作图像,您可能会发现使用index 作为id 会有点麻烦。例如,从状态中删除丢弃的图像将重新索引图像数组。所以你可以考虑为id 属性使用不同的东西。

希望这会有所帮助。

【讨论】:

  • 我正在尝试在我的代码中实现这一点,但我没有找到关于不同 internalDNDType 的好的文档。我看到您使用“text/plain”和“text”作为参数。如果我要拖动图像,我会使用什么?
  • 啊,好问题。并非所有浏览器都支持直接拖动图像。所以使用类型text 并在dataTransfer 中传递图像的URL。然后使用 URL 在新位置设置新图像或缩略图。由于图像将在本地缓存中,因此所有这些在时间上都是不明显的。
【解决方案2】:

Key 是一个道具,而不是一个属性。道具不会出现在 DOM 中,它们会被传递到子组件中。

key 是一个特殊的道具,可以在列表中的普通元素上。它不会传播到 DOM 中。看看本文中的一些代码笔。 https://reactjs.org/docs/lists-and-keys.html

所以

<span
  key={index}
  id={index}
>
  {image}
</span>

将呈现为:

<span id=*value_of_index*> *value_of_image* </span>

检查元素不会显示任何键。

【讨论】:

  • 请从其中一个示例中解释这一点:'当您没有用于渲染项目的稳定 ID 时,您可以使用项目索引作为键作为最后的手段 '
  • 使用 index 没问题,但是 key 仍然不会出现在 Dom 中
  • 我喜欢这些编辑,谢谢(我没有对你投反对票)。如您所见,无论 OP c-n-p 从何处获取代码,dragstart 都会尝试使用 id,尽管不正确。 OP的代码无法正常工作。 OP 需要在实时编辑器中提供有效的解决方案。
  • Randy,我对你想要的实时解决方案感到困惑。我说代码不起作用。我正试图找出原因。
  • @kreed - 我在回答中为您提供了一个可行的解决方案,并描述了您在代码中遇到的问题。请检查我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多