2

I am making an E-Commerce react native app and in the CART section of the app, I want every item added in a cart with the same ID (categoryID as you can see in the console) to render only once, but in my case if I add 3 items with same id in the cart, I will see 3 different listItems of their respected items. I want my map function to show 1 list item if there are multiple items with same id with quantity getting added. My code so far is just rendering every selected product as a separate item:

renderItems() {
let items = [];
this.state.cartItems.map((item, i) => {
  console.log(item)
  items.push(
    <ListItem
      key={i}
      last={this.state.cartItems.length === i + 1}
      onPress={() => this.itemClicked(item)}
    >
      <Thumbnail square style={{ width: 100, height: 100 }} source={{ uri: item.productdetail.image }} />
      <Body style={{ paddingLeft: 10 }}>
        <Text style={{ fontSize: 16 }}>

          {item.productdetail.name}

        </Text>

        <Text style={{ fontSize: 14, fontStyle: 'italic' }}>Price: {item.productdetail.price}</Text>
        <Text style={{ fontSize: 14, fontStyle: 'italic' }}>Quantity: {item.quantity > 1 ? item.quantity : 1}</Text>

      </Body>
      <Right>
        <Button style={{ marginLeft: -25 }} transparent onPress={() => this.removeItemPressed(item)}>
          <Icon size={30} style={{ fontSize: 30, color: '#95a5a6' }} name='ios-remove-circle-outline' />
        </Button>
      </Right>
    </ListItem>
  );
});
return items;}

The result of console.log is as follows enter image description here

This is how my cart looks like enter image description here

Now as you can see the cart should display only one listItem with same product have quantity=18

Bahman Parsa Manesh
  • 2,314
  • 3
  • 16
  • 32
Syyam Noor
  • 474
  • 5
  • 15

2 Answers2

2

Considering you have a simple data set like this :

const rawItemsData = [
    {id: 1, qty: 2},
    {id: 1, qty: 3},
    {id: 2, qty: 1},
    {id: 1, qty: 2},
    {id: 2, qty: 5},
    {id: 3, qty: 6}
];

If you want to get an array with unique item ids and summed qty, you can use reduce :

const uniqueItemsData = rawItemsData.reduce((prev, item) => {
    const existingItem = prev.find(({id}) => id === item.id);
    if(existingItem)
        existingItem.qty = existingItem.qty + item.qty;
    else
        prev.push(item);
   return prev;
 }, []); //-> [ { id: 1, qty: 7 }, { id: 2, qty: 6 }, { id: 3, qty: 6 } ];


 //Then you can use your code : 
 uniqueItemsData.map((item, id) => {
     //..
 });
Logar
  • 1,248
  • 9
  • 17
  • In prev.find(({id}) => id === item.id);, what will I get in the 'id'? – Syyam Noor Aug 10 '18 at 08:08
  • This line is using object destructuring. `find` will loop through the existing items and execute a callback. In this callback, the variable `id` will hold the value of the current item `id` property – Logar Aug 10 '18 at 08:10
  • put it simply, you could also write : `prev.find((testItem) => testItem.id === item.id);` – Logar Aug 10 '18 at 08:11
  • You edited my answer, which made it less readable so I rejected the edit. But yes, I think you had it right – Logar Aug 10 '18 at 08:22
  • I am having a type error: '' undefined is not an object (testItem.productDetail)" – Syyam Noor Aug 10 '18 at 09:05
  • Can you suggest me that line according my data? – Syyam Noor Aug 10 '18 at 09:05
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177794/discussion-between-logar-and-abbu-jan). – Logar Aug 10 '18 at 09:08
0

In this case, you have to make a simple control before pushing, whether the item exists or not. It's up to you to design it:

For example, you could create another list that holds the unique items. In such a page, I believe it is useful to hold the unique items, you might need related information somewhere else too. And this list shouldn't require setState because it's just for the control.

this.state.uniqueItems = [];

In each push, add the item to the uniqueItems. Do not use setState here because it will cause redundant render:

this.state.uniqueItems.push(item);

In the map function, before pushing, check if it the id exists in the unique list. You could use a simple for loop, or lodash library, or Array's find method here.

Faruk Yazici
  • 2,344
  • 18
  • 38