Reputation: 3
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
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.
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