Reputation: 101
I'm trying to splice on a DoubleClick event an item from my list(inventory) but something is not working as I want it. Would be nice if someone could be so kind and help me out to figure out what I'm doing wrong here. For the Info: when I try to slice an item it gets sliced but it is every time the first item and the second item loses all the content inside:
function Inventory() {
const [datas, setData] = useState([
{
id: 1,
label: "Sword",
itemname: "grey_sword",
pieces: 1,
type: "weapon",
},
{
id: 2,
label: "Knife",
itemname: "grey_knife",
pieces: 1,
type: "weapon",
},
]);
useEffect(() => {
const getItems = (data) => {
setData(data);
} // this section is for something else
}, [datas]);
const deleteItem = (index) => {
const test = ([], datas)
test.splice(index, 1)
setData([{test : datas}]);
}
const renderItem= (data, index) => {
return (
<Item
key={data.id}
id={data.id}
type={data.type}
label={data.label}
index={index}
name={data.itemname}
pieces={data.pieces}
deleteItem={deleteItem}
/>
)
}
return (
<div className="inventory-holder">
<div className="inventory-main">
<div className="inventory-information">
<div className="inventory-title">
Inventory
</div>
<div className="inventory-weight-info">
0.20 kg / 1.00 kg
</div>
<div className="inventory-buttons">
<button className="refresh-button" tabIndex="-1"><FontAwesomeIcon icon={faRedo} /></button>
<button className="close-button" tabIndex="-1"><FontAwesomeIcon icon={faTimes} /></button>
</div>
</div>
<div className="items-holder">
<div>{datas.map((data, i) => renderItem(data, i))}</div>
</div>
</div>
</div>
)
}
export default Inventory;
and that would be the Item:
const Item = ({ index, id, type, label, name, pieces, deleteItem }) => {
const useItem = e => {
const type = e.target.getAttribute("itemType");
const index = e.target.getAttribute("data-index");
const pieces = e.target.getAttribute("itempieces");
console.log(type + " " + index + " " + pieces )
if(parseInt(pieces) <= 1){
deleteItem(parseInt(index));
}
}
return(
<div data-index={id} onDoubleClick={useItem} className="inventory-item" itemType={type} itemname={name} itemlabel={label} itempieces={pieces}>
<img className="item-pic" src={chosedtype} ></img>
<div className="item-label">{label}</div>
<div className="item-number-pieces">{pieces}</div>
</div>
);
};
export default Item;
Upvotes: 0
Views: 738
Reputation: 1386
Your Item is way too complicated:
You can directly use the props without passing them through your div
.
const Item = ({ index, id, type, label, name, pieces, deleteItem }) => {
const useItem = () => {
console.log(type + " " + index + " " + pieces )
if(pieces <= 1){
deleteItem(index);
}
}
return(
<div data-index={id} onDoubleClick={useItem} className="inventory-item">
<img className="item-pic" src={chosedtype} ></img>
<div className="item-label">{label}</div>
<div className="item-number-pieces">{pieces}</div>
</div>
);
};
export default Item;
Then your deleteItem
function doesn't do what you want:
const deleteItem = (index) => {
const test = ([], datas); //test = datas;
test.splice(index, 1); // test = test without the item at the index
setData([{test : datas}]);//data = [{test: datas}] so an array with an object with the property test = datas (the original array).
}
You should change your deleteItem
to something like:
const deleteItem = (index) => {
const newArray = datas.filter((item, i) => i !== index);
setData(newArray);
}
Upvotes: 1
Reputation: 203091
Array::splice does an in-place mutation.
The
splice()
method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.
The main issue here is state mutation.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
const test = ([], datas)
ends up saving the state reference data
to test
, which is then mutated by test.splice(index, 1)
, and then strangely enough is overwritten back into state differently setData([{ test: datas }]);
.
A common pattern is to use array::filter instead and filter on the index. filter
returns a new array.
const deleteItem = (index) => {
setData(datas => datas.filter((_, i) => i !== index);
}
Upvotes: 3