user1821807
user1821807

Reputation: 3

Delete draggable object in react-dnd

I'm using react-dnd. I want to delete a draggable object once it's been used. I took the react-dnd multiple type example and added a delete on drop.

Current behavior: 1. Drag Banana, the top right dustbins is highlighted 2. Drag Bottle into either of the dustbins on the left 3. Drag Banana again, now the left two dustbins are highlighted

Expected behavior: 1. Drag Bottle into either of the dustbins on the left 2. Drag Banana, the top right should be highlighted

What is going on here, and how do I fix it?

https://codesandbox.io/s/pensive-wildflower-q2oxo?file=/src/Dustbin.jsx

Upvotes: 0

Views: 3472

Answers (1)

gdh
gdh

Reputation: 13682

You are using array index as key to the boxes and doing removals. Don't use indexes as key specially when dealing with item-removal operations. Instead, maintain a unique id for Boxes. Also update the state of the boxes properly.

Edit react dnd drag issue fix

Code Snippet

const Container = () => {
  const [dustbins, setDustbins] = useState([
    { accepts: [ItemTypes.GLASS], lastDroppedItem: null },
    { accepts: [ItemTypes.FOOD], lastDroppedItem: null },
    {
      accepts: [ItemTypes.PAPER, ItemTypes.GLASS, NativeTypes.URL],
      lastDroppedItem: null
    },
    { accepts: [ItemTypes.PAPER, NativeTypes.FILE], lastDroppedItem: null }
  ]);
  const [boxes, setBoxes] = useState([
    { id: 1, name: "Bottle", type: ItemTypes.GLASS },
    { id: 2, name: "Banana", type: ItemTypes.FOOD },
    { id: 3, name: "Magazine", type: ItemTypes.PAPER }
  ]);
  const [droppedBoxNames, setDroppedBoxNames] = useState([]);
  function isDropped(boxName) {
    return droppedBoxNames.indexOf(boxName) > -1;
  }
  const handleDrop = useCallback(
    (index, item, id) => {
      const { name } = item;
      setDroppedBoxNames(prev => [...prev, name]);
      // setDroppedBoxNames(
      //   update(droppedBoxNames, name ? { $push: [name] } : { $push: [] })
      // );
      setBoxes(prev => prev.filter(x => x.id !== id));
      // setBoxes(update(boxes, { $splice: [[item.id, 1]] }));
      setDustbins(
        update(dustbins, {
          [index]: {
            lastDroppedItem: {
              $set: item
            }
          }
        })
      );
    },
    [droppedBoxNames, boxes, dustbins]
  );
  return (
    <div>
      <div style={{ overflow: "hidden", clear: "both" }}>
        {dustbins.map(({ accepts, lastDroppedItem }, index) => (
          <Dustbin
            accept={accepts}
            lastDroppedItem={lastDroppedItem}
            onDrop={item => handleDrop(index, item)}
            key={index}
          />
        ))}
      </div>

      <div style={{ overflow: "hidden", clear: "both" }}>
        {boxes.map(({ name, type, id }, index) => (
          <Box
            key={id}
            id={id}
            name={name}
            type={type}
            isDropped={isDropped(name)}
          />
        ))}
      </div>
    </div>
  );
};
export default Container;

Upvotes: 1

Related Questions