这是我对React的第一次尝试。我正在尝试构建一个UI,可以在其中拖放图像并移动它们的顺序。我意识到,首先,这将要求每个图像都具有唯一的密钥,但是我找不到正确的方法。我不明白为什么,即使我显式分配了一个键,当我在控制台上查看对象时,它仍然为null。我尝试过:
<div>
{this.props.imageArray.map((image, index) => (
<span
key={index}
>
{image}
</span>
))}
</div>;
哪个仍然给我一个null
的键(我也尝试为外部div分配自己的键,但是那也不起作用)。
我已经读到,如果未指定key,则默认为数组中元素的id(当未指定key但这是预期值时,我仍会得到null值),因此我尝试手动分配
<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;
答案 0 :(得分:1)
这是一个有效的示例,它将整数数组替换为图像数组。我将图像部分留给您,因为在您的示例中这似乎并不完整。解决方案的核心部分是名为“ images.js”的文件。
https://codesandbox.io/s/013jrvn2pp
您的代码只有几个问题:
id
财产。<span key={index} id={index} >
dragStart
事件的处理程序与事件API中的函数签名不匹配。这意味着您必须从处理程序中的事件对象派生id
属性值(我已经在提供的解决方案中完成了此操作):onDragStart = (ev, id) => { ... }; Must be: onDragStart = (ev) => { ... };
.dataTransfer()
方法。该setData()
API需要将数据类型作为第一个参数,将值作为第二个参数。 getData()
API仅需要数据类型。 您可能会发现,如果尝试通过index
(也是数组索引)来操纵图像,那么将id
用作id
会有些麻烦。例如,从状态中删除掉的图像将重新索引图像阵列。因此,您可以考虑为id
属性使用其他内容。
希望这会有所帮助。
答案 1 :(得分:0)
键是道具,不是属性。道具未显示在DOM中,而是传递到子组件中。
键是一个特殊的道具,可以放在列表中的普通元素上。它不会传播到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>
检查元素不会显示任何键。