0

In my state I have an array, which I mapped in render function:

State

this.state = {
        newItem: {
            name: "",
            amount: 0
        },
        products: [
            {
                name: "Item",
                amount: 5
            },
            {
                name: "Item",
                amount: 5
            },
            {
                name: "Item",
                amount: 5
            }
        ]
    }

I want to delete element from the array products by clicking in button of that element. But what I attempted to do, everything fails. I searched a lot and find logically the most common solution but it didn't work too. Here is the delete function:

Delete function

delete(e) {
  this.setState(prevState => ({ products: prevState.products.filter((product) => {
      return product !== e.target.value
  })}))
  console.table(this.state.products)
}

Mapped JSX code

            {
                this.state.products.map((item, index) => {
                    return(
                        <div key={index}>
                            <input readOnly value={this.state.products[index].name} type="text" />
                            <button disabled>-</button>
                            <input readOnly value={this.state.products[index].amount} type="number" />
                            <button disabled>+</button>
                            <button onClick={(e) => this.delete(e)}>Delete</button>
                        </div>
                    )
                })
            }
2
  • 1
    Maybe this answer can help you out. Commented Sep 21, 2019 at 18:45
  • @HMR thanks this answer was interesting too Commented Sep 22, 2019 at 8:34

4 Answers 4

3

You need to pass index of that element into delete which will be removed like below.

<button onClick={() => delete(index)}>Delete</button>

Then you can remove that element easily.

delete = index => {
  this.setState(prevState => 
    ({
        products: prevState.products.filter((product, i) => i !== index)
    })
  );
}
Sign up to request clarification or add additional context in comments.

2 Comments

splice actually modifies the array, I would prefer using filter method
@Antonio delete one parenthesis like this : ` products: prevState.products.filter((product, i) => i !== index)` like works only like this
1

Note that setState is asynchronous, so using console.log(this.state.products) immediately after calling setState will not print the updated products. You can pass a callback in the second parameter of setState, it will be executed once setState is completed.

The other problem comes from the delete function. You are using e.target.value which is an empty string because the button has no value.

You can fix this with the following code :

delete(product) {
  this.setState(prevState => ({
    products: prevState.products.filter(p => p !== product)
  }), 
  () => console.log(this.state.products));
}

In the JSX code, I pass the product in the first argument of the delete function :

{
  this.state.products.map((product, index) => (
    <div key={index}>
      <input readOnly value={product.name} type="text"/>
      <button disabled>-</button>
      <input readOnly value={product.amount} type="number"/>
      <button disabled>+</button>
      <button onClick={() => this.delete(product)}>Delete</button>
    </div>
  ))
}

2 Comments

Sorry, but it doesn't work. It just doing nothing when I click
But whatever, I find the right answer and you gave me good advice, it at least deserves an upvote. Thank you!
1

A simplified example of how to make item specific buttons on a mapped list:

delete = (id) => {
  this.setState(products: this.state.products.filter((item, index) => index !== idx));
}

1 Comment

Your algorithm of delete function is right, but in this case, I need exactly the code what I wrote in the edit, thank you.
0

here is the solution and working example here https://codesandbox.io/s/dawn-tdd-js8yz

state = {
    newItem: {
        name: "",
        amount: 0
    },
    products: [
        {
            name: "Item1",
            amount: 5
        },
        {
            name: "Item2",
            amount: 5
        },
        {
            name: "Item3",
            amount: 5
        }
    ]
}

  delete(e: any) {
    
    var products = this.state.products.filter((product) => {
      return product.name !== e.name
    });

    console.log(products)

    this.setState({products: products})
    console.table(this.state.products)
  }

  render() {
    const { products } = this.state;
    return (
      <>
      {products.map((x, index) => {
        return <div key={index}>
        <input readOnly value={this.state.products[index].name} type="text" />
        <button disabled>-</button>
        <input readOnly value={this.state.products[index].amount} type="number" />
        <button disabled>+</button>
        <button onClick={this.delete.bind(this, x)}>Delete</button>
    </div>
      })}
      </>
    )
  }

1 Comment

It is to complex, but anyway it works, it deserves at least an upvote. Thank You!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.