Элементы с одинаковыми именами, генерирующие одинаковые клавиши при перетаскивании

#javascript #reactjs #react-dnd

Вопрос:

Мне нужна возможность иметь два одинаковых элемента, в то время как они не дублируются при перетаскивании на доску. Но когда я перетаскиваю элемент, существующий на доске, он регистрирует «перемещение».

Вместо этого он должен добавить другой одноименный элемент с другим ключом. Мне трудно найти свою ошибку, пожалуйста, помогите.

Это мой код

 import { React, useState } from "react";
import { useDrop } from "react-dnd";
import { ItemTypes } from "../ItemTypes";
import Items from "./Items";

const Board = () => {
    const [components, setComponents] = useState([]);

    const onDelete = (id) => {
        console.log(components);
        console.log(id);
        setComponents(components.filter((component) => component.key !== id));
    };

    const [, drop] = useDrop(() => ({
        accept: ItemTypes.COMPONENT,
        drop: (item) => {
            console.log(item.name, item.key);
            if (item.key === undefined) {
                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");
            }
        },
    }));

    return (
        <div ref={drop} className="board">
            <Items components={components} onDelete={onDelete} />
        </div>
    );
};

export default Board; 

это компонент(внешний, должен преобразовываться в элемент при перетаскивании)

 import React from "react";
import { useDrag } from "react-dnd";
import { ItemTypes } from "../ItemTypes";

const Component = ({ component }) => {
    const [, drag] = useDrag(
        () => ({
            type: ItemTypes.COMPONENT,
            item: component,
        }),
        []
    );

    return (
        <div ref={drag} className="component">
            <h4>{component.name}</h4>
        </div>
    );
};

export default Component; 

Это пункт(на текущей доске)

 import React from "react";
import { useDrag } from "react-dnd";
import { ItemTypes } from "../ItemTypes";
import { FaTimes } from "react-icons/fa";

const Item = ({ component, onDelete, key, left, top }) => {
    const [{ isDragging }, drag] = useDrag(
        () => ({
            type: ItemTypes.COMPONENT,
            item: component,
            collect: (monitor) => ({
                isDragging: monitor.isDragging(),
            }),
        }),
        [key, left, top]
    );

    if (isDragging) {
        return <div ref={drag} />;
    }
    return (
        <div ref={drag} className="item">
            <h4>
                {component.name}
                {<FaTimes onClick={() => onDelete(component.key)} />}
            </h4>
        </div>
    );
};

export default Item; 

Комментарии:

1. Можете ли вы добавить свою логику перетаскивания? Кроме того, ваш компонент, в котором вы создаете ключ

2. генератор ключей находится в блоке if

3. В консоли drop добавьте еще одно свойство, чтобы увидеть, какое значение вы получаете console.log(item.name, item.key, typeof item.key); . Если тип item.key не определен, он перейдет в ваш блок else. Как правило, вы можете изменить свое состояние на if (item.key) вместо того, чтобы проверять undefined .

4. Я сменил его на if(!item.key) , но все осталось по-прежнему. Я не могу понять, почему component у меня есть ключ от item .

5. const newItem = Object.assign(item, itemKey); измените это на const newItem = Object.assign({},item, itemKey);

Ответ №1:

Итак, проблема в том, как мы Object.Assign() правильно используем. Он выполняет по крайней мере 2 работы.

  1. Обновляет существующий объект. Object.assign(item, itemKey); обновляет ключ элемента.
  2. Создает новый объект Object.assign({},item, itemKey); Это создает совершенно новый объект, поскольку он объединяет старые свойства с пустым объектом.

Вместо этого вы могли бы использовать оператор распространения, чтобы избежать путаницы. const newItem = {...item, itemKey}; это бы сработало.