Set state from content of another item in the state

Viewed 62

I'm trying to setState of order to be the content of catalog only if it's true, I guess I need to make a function that always listen if the state of order changes.

This is my state

constructor(props) {
  super(props)
  this.state = {
    catalog: [
      {
        photo: 'https://via.placeholder.com/164x168',
        title: 'FirstItem',
        description: 'Fugiat nulla incididunt laborum et esse adipisicing esse aliquip.',
        size_m: { size: 'M', price: 5000, id: 'FTM', selectedIndicator: '', isSelected: false },
        size_l: { size: 'L', price: 8000, id: 'FTL', selectedIndicator: '', isSelected: false },
        size_xl: { size: 'XL', price: 10000, id: 'FTXL', selectedIndicator: '', isSelected: false },
      },
      {
        photo: 'https://via.placeholder.com/164x168',
        title: 'SecondItem',
        description: 'Fugiat nulla incididunt laborum et esse adipisicing esse aliquip.',
        size_m: { size: 'M', price: 5000, id: 'SCRM', selectedIndicator: '', isSelected: false },
        size_l: { size: 'L', price: 8000, id: 'SCRL', selectedIndicator: '', isSelected: false },
        size_xl: { size: 'XL', price: 10000, id: 'SCXL', selectedIndicator: '', isSelected: false },
      },
    ],
    order: []
  }
}

Example: In case of size_m of first item and size_l of second item in catalog change isSelected to true, order state should update to

order: [
  {
    size_m: { size: 'M', price: 5000, id: 'FTM', selectedIndicator: '', isSelected: true },
    size_l: { size: 'L', price: 8000, id: 'SCRL', selectedIndicator: '', isSelected: true }
  }
]

This is my handler function

  setOrder = () => {
    const { catalog } = this.state
    let catalogOrder = []
    catalog.map(item => {
      if(item.size_m.isSelected) {
        catalogOrder = [item]
      }
      return this.setState({order: catalogOrder})
    })
  }
2 Answers

Change your handler function to something like this. Use forEach instead of map, take the setState call out of the callback, and remove return from the last line:

setOrder = () => {
  const { catalog } = this.state
  let catalogOrder = []
  catalog.forEach(item => {
    if(item.size_m.isSelected) {
      catalogOrder.push(item)
    }
  })
  this.setState({order: catalogOrder})
}

The map method maps a modification of the elements in the original array onto a new array -- for example, you want to multiply every number in your array by 3 -- and I don't think that's what you're trying to do here. Read more about map in MDN.

EDIT 1: The above will not solve your problem entirely, as your code currently only checks for medium sizes. I think one way to achieve what you're trying to do is to make a new property under each catalog item that keeps track of the size that is selected, so for example:

this.state = {
    catalog: [
      {
        photo: 'https://via.placeholder.com/164x168',
        title: 'FirstItem',
        description: 'Fugiat nulla incididunt laborum et esse adipisicing esse aliquip.',
        selectedSize: '',   // this can hold whatever object or reference you need
        ...
      },
        ...
    ]
...
}

EDIT 2: To trigger the setOrder handler appropriately, take a look at this article for watching changes in a state with componentDidUpdate()

This should do the job.

 setOrder = () => {
    const { catalog } = this.state


     var catalogOrder = [];
        catalog.forEach(i=>{
          if(i.size_m.isSelected){
             catalogOrder.push(i.size_m);
           }else if(i.size_xl.isSelected ){
             catalogOrder.push(i.size_s);
           }else if(i.size_l.isSelected){
             catalogOrder.push(i.size_l);
            }
        });
        this.setState({order: catalogOrder});

      }
Related