I am trying to delete an object in an array in my state. I want to do this by using a onclick handler on items from a map function.
So when I click on a specific item, I have tried many things. I have tried the filter function by trying to pass down the item from the map function and then filtering out the array excluding the item provided as argument, I've tried splice but all doesn't seem to work. With splice, It always delete the last item instead of the Item I click on.
What am I not seeing? I know there are a lot of similiar questions but I've tried many of the answers over there but nothing seems to work.
Filter try
JSX
{this.state.product.ingredients.map((item) => {
return (
<p className="text-xs text-white bg-brand rounded p-4 mt-2 mb-2 mr-2 inline-block cursor-pointer" key={item.name} onClick={({item}) => this.deleteTag({item})}>{item.name}</p>
);
})}
Method
deleteTag(item) {
let product = {...this.state.product};
product.ingredients.filter((ingredient) => {
return ingredient !== item;
});
this.setState({product: product});
}
Splice
JSX
{this.state.product.ingredients.map((item) => {
return (
<p className="text-xs text-white bg-brand rounded p-4 mt-2 mb-2 mr-2 inline-block cursor-pointer" key={item.name} onClick={this.deleteTag}>{item.name}</p>
);
})}
Method
deleteTag(e) {
let product = {...this.state.product};
var index = product.ingredients.indexOf(e.target.value)
product.ingredients.splice(index, 1);
this.setState({product: product});
}
Example of the array with one object (objects/items are added with another function)
ingredients: [{name: 'Salad', value: 1}],
I'm not sure that you are updating your state correctly but instead mutating it. Could you try this:
deleteTag(item) {
this.setState(prevState => {
return {
product: {
...prevState.product,
ingredients: prevState.product.ingredients.filter((ingredient) => ingredient !== item)
}
}
});
}
Edit your onClick to pass the item
from map
:
onClick={() => this.deleteTag(item)}
filter
returns a new array instead of modifying the array in place.
{...this.state.product}
only creates a shallow copy, so you should not modify product.ingredients
in place anyway, which is why your second attempt failed as well.
Try this:
this.setState(prevState => ({
product: { ...prevState.product, ingredients: prevState.product.ingredients.filter(...) },
}));
You need to pass the item
to your callback. You're currently using event.target.value
, but your <p>
element doesn't have a value
. Use bind
to partially apply your callback.
JSX:
{this.state.product.ingredients.map((item) => (
<p
className="text-xs text-white bg-brand rounded p-4 mt-2 mb-2 mr-2 inline-block cursor-pointer"
key={item.name}
onClick={this.deleteTag.bind(item)}>
{item.name}
</p>
))}
the first argument to your callback will be your item
object because of the partial function application, it'll no longer be the click event. (If you still need the click event, it will be the second argument.)
Method:
deleteTag(item, /* event */) {
let product = {...this.state.product};
const index = product.ingredients.indexOf(item.value)
product.ingredients.splice(index, 1);
this.setState({product: product});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.