Home > Software design >  Dynamically add item into react-bootsrap accordion
Dynamically add item into react-bootsrap accordion

Time:07-11

I'm getting my data from database. Then I would like them to be categorized by "item_category" and have them in react-bootstrap accordion.

So far I have this:

<Accordion>
            {
                items.map((item, index) => {
                    if(item.item_category === "Submachines"){
                        return (
                            <Accordion.Item eventKey={index} key={index}>
                                <Accordion.Header>{item.item_category}</Accordion.Header>
                                <Accordion.Body>
                                    <Item key={index} 
                                    itemName={item.item_name} 
                                    itemImageUrl={item.item_image} 
                                    itemCategory={item.item_category}
                                    sellPrice={item.sell_price}
                                    buyPrice={item.buy_price}
                                    slotSize={item.slot_size}
                                    />
                                </Accordion.Body>
                            </Accordion.Item>
                        );
                    }
                })  
            }
            
        </Accordion>

But It's kind of wrong as this is creating an accordion item for each item in items array. What I would like to have is for each category to have only one accordion item.

Can someone point me in right direction, please ? Thanks

CodePudding user response:

You can either get items from backend already grouped by category or you can ask for category while iterating over your items, save them grouped by category and only then render Accordion.Item for each category:

  • Iterate over items
  • Create an object for categories
  • Look up if item.item_category exist as property in yur categories object
  • If no, first create property, then add item as value in a list
  • If yes, add item as value in a list
  • When you are done with iterating, iterate over your categories object and render an Accordion.Item for every property (=category).

Example categories object:

const categories = {
  "catA": [ item1, item2, item3],
  "catB": [ item4, item5, item6],
  "catC": [ item7, item8, item9]
}

Edit:

Please look into following codesandbox: https://codesandbox.io/s/charming-mirzakhani-9n344i

 const categories = {};
  for (const item of items) {
    if (item.item_category in categories) {
      categories[item.item_category].push(item);
    } else {
      categories[item.item_category] = [item];
    }
  }
  return (
    <Accordion>
      {Object.entries(categories).map((entry) => {
        const category = entry[0];
        const itemList = entry[1];
        return (
          <Accordion.Item eventKey={category} key={category}>
            <Accordion.Header>{category}</Accordion.Header>
            <Accordion.Body>
              {itemList.map((item) => (
                <span>{item.name} </span>
              ))}
            </Accordion.Body>
          </Accordion.Item>
        );
      })}
    </Accordion>
  );

CodePudding user response:

A cleaner way to achieve this, first you need get grouped category from items and then create Accroding.Item for each category like this:

const categorySet = new Set();

items.map((item) => categorySet.add(item.item_category));


const categoryArray = [...categorySet]


categoryArray.map(category => <According.Item .... rest of the component code
  • Related