ISAAC
ISAAC

Reputation: 159

Doesn't remove the right item in react

My state cart value (shirtsList) is a separate file with an array of T-shirt objects. What I'm trying to do is delete an item from the array by clicking on the REMOVE button that is in the itemOptions.js component file. My remove handler is handleRemoveItem, as you can see in the App.js file.

App.js file:

import React, { Component } from 'react';
import Item from './Components/item';
import ItemProperties from './Components/itemProperties';
import { shirtsList } from './shirtsList';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      quantity: [],
      totalItems: 0,
      size: ['S', 'M', 'L'],
      color: ['red', 'blue', 'black'],
      cart: shirtsList
    }
  }

  handleRemoveItem = (shirt) => {
    console.log(shirt)
    let index = this.state.cart.filter((item) => {
      return shirt !== item
    })
    this.setState({cart: index})
  }


  render() {
    this.setState.quantity = shirtsList.map((shirt, i) => {
      return ( 
        this.state.quantity.push({amount: shirtsList[i].quantity})
      ) 
    })

    return (
      <div>
        <div className="itemInTheCart">

        {
          this.state.cart.map((shirt, i) => {
          return ( 
            <Item 
              onClick={(e) => this.handleRemoveItem(shirt)}
            />
            ) 
          })
        }
        </div>
      </div>
    );
  }
}

export default App;

item.js component file:

import React from 'react';
import ItemOptions from './itemOptions';

const item = (props) => {
    return (
        <div className="item">
            <ItemOptions onClick={props.onClick}/>
        </div>
    );
}

export default item;

itemOptions.js component file:

import React from 'react';

const itemOptions = (props) => {
    return (
        <div className="itemOptions">
            <p className="itemOptions__remove" onClick={props.onClick}>X REMOVE |&nbsp;</p>
        </div>
    );
}

export default itemOptions;

Upvotes: 2

Views: 732

Answers (2)

Hemadri Dasari
Hemadri Dasari

Reputation: 33974

There are so many mistakes that you are doing in App.js

  1. Never do setState in render.
  2. The way you are doing setState isn’t correct
  3. Never mutate state directly. You must use setState to modify state value
  4. Try to keep your render as much as clean by availing react provided life cycle methods.
  5. The way your pushing items to an array is not recommended because you are mutating directly

The proper way of pushing into an array using setState in React would be something like below

  render() {
       shirtsList.map((shirt, i) => {
            let obj = {};
            obj.amount = shirt.quantity;
            this.setState(prevState => ({
                 quantity: [...prevState.quantity, obj]
            }));
        })
   }

Upvotes: 4

devserkan
devserkan

Reputation: 17608

As explained in the comments (and now previously provided answer by @Think-Twice) what you are trying to with this.setState.quantity = shirtsList.ma... in your render method is wrong. So avoid doing something like that. But, this part seems not related to removing the items from the cart? So, apart from this part of your code, actually it works.

I've changed the code slightly.

  • Removed the bad part.
  • Pass the shirt to the Item component then to ItemOptions component. Also, this second component is actually not necessary. You are not doing anything in Item component here. Just passing the props.
  • I triggered the remove function in ItemOptions component, so no need to pass anything in the parent one by invoking the function. We have the shirt here, so used it.
  • In the remove function, instead of comparing objects, I've used ids. So, stick to this strategy if possible.
  • Added some unnecessary style.

const shirtsList = [
  { id: 1, color: "red", size: "S", quantity: 10 },
  { id: 2, color: "blue", size: "M", quantity: 20 },
  { id: 3, color: "yellow", size: "L", quantity: 30 },
  { id: 4, color: "red", size: "S", quantity: 40 },
  { id: 5, color: "blue", size: "M", quantity: 50 },
]

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      quantity: [],
      totalItems: 0,
      size: ['S', 'M', 'L'],
      color: ['red', 'blue', 'black'],
      cart: shirtsList
    }
  }

  handleRemoveItem = (shirt) => {
    const newCart = this.state.cart.filter((item) => {
      return shirt.id !== item.id
    })
    this.setState({cart: newCart})
  }


  render() {
    return (
      <div>
        <div className="itemInTheCart">
        {
          this.state.cart.map((shirt, i) => {
          return ( 
            <Item
              key={shirt.id}
              onClick={this.handleRemoveItem}
              shirt={shirt}
            />
            ) 
          })
        }
        </div>
      </div>
    );
  }
}

const Item = (props) => {
  return (
    <div className="item">
      <ItemOptions shirt={props.shirt} onClick={props.onClick} />
      {/* or you can use 
      <ItemOptions {...props} />
      */}
    </div>
  );
}

const ItemOptions = (props) => {
  const handleClick = () => props.onClick( props.shirt );
  return (
    <div className="itemOptions" style={{background: `${props.shirt.color}`}}>
      <p>ID: {props.shirt.id}&nbsp;
      Size: {props.shirt.size}&nbsp;
      Quantity: {props.shirt.quantity}&nbsp;
      Color: {props.shirt.color}</p>
      <button onClick={handleClick}>X REMOVE</button>
    </div>
  );
}


ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Upvotes: 2

Related Questions