1

I have this array that has this structure please check the code down below , my end results should look like the following :

  • veg
  • apple
  • carrot

  • meat
  • chicken
  • steak

my current results are

apple carrot chicken steak

since I cannot structure the array other wise and don't want to go in to deep nesting or even nest loops which I doubt it will work in react any idea how to achieve the previous results using map , where I map through group only once to create the group name and to then add the items related to that group inside that group?, food for thought : could conditional rendering be also leveraged here ? I was able to only get either the group multiple times or the items only..

const arr = {
  itmes: [
    { id: 1, group: "veg", item: "apple" },
    { id: 2, group: "veg", item: "carrot" },
    { id: 3, group: "meat", item: "chicken" },
    { id: 4, group: "meat", item: "steak" }
  ]
};

function App() {
  return (
    <div>
      {arr["itmes"].map(
        (item) => item.group
        //item.item
      )}
    </div>
  );
}

Codesanadbox

2
  • 1
    Just do (item) => i<li>{tem.group}</li> See Rendering multiple components for explanation Commented Sep 24, 2021 at 16:18
  • still this doesn't solve the issue of the array structure that I have. Commented Sep 24, 2021 at 16:23

3 Answers 3

3

Im very new to javascript, but like hgb123's answer, something like this inside a render or return block:

<div className="myClass">
  {myList.map((eachItemInList) => (
    <ReactComponent certainProp={eachItemInList} />
   ))}
</div>

works perfectly for a list like this one:

const myList = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6']

hope this helped someone!

Sign up to request clarification or add additional context in comments.

Comments

1

You should wrap the items first and render the grouped ones

const groupItems = items =>
  items.reduce((groupedItems, item) => {
    if (!groupedItems[item.group]) {
      groupedItems[item.group] = []
    }

    groupedItems[item.group].push(item)

    return groupedItems
  }, {})

const items = Object.entries(groupItems(arr.items)).map(
  ([groupName, items]) => (
    <React.Fragment>
      <li>{groupName}</li>
      {items.map(item => (
        <li>{item.item}</li>
      ))}
    </React.Fragment>
  )
)

Edit vibrant-sky-jwrmf

Comments

1

Option 1

First, make sure your array is sorted by Group:

const sorted = arr["itmes"]
    .sort((a, b) => (a.group || '').localeCompare(b.group));

Then you can render and conditionally add another heading element whenever the group name changes:

<ul>
    {data.map((d, id) => (
        <>
            ((id > 0 || d.group !== data[id - 1].group) ? <li key={`${id}-h`}><b>{d.group}</b></li> : undefined)
            <li key={`${id}-v`}>{d.item}</li>
        </>
    ))}
</ul>

Extra: Custom group sorting

If you need to custom sort the array according to another array:

const sortLtu = ['veg', 'apple', 'meat'];
data.sort((a, b) => sortLtu.indexOf(a.group) - sortLtu.indexOf(b.group));

Option 2: Util function

If you end u doing this often you may create a util function:

Array.prototype.groupBy = function(cb) {
    const groups = [];
    this.forEach((d, id, arr) => {
        const g = cb(d, id, arr);
        let group = groups.find(_g => _g.group === g);
        if (!group) {
            group = { group: g, items: [] };
            groups.push(group);
        }
        group.items.push(d);
    })
    return groups;
}

And then use it like

{data.groupBy(i => i.group).map((bundle, ix) => (
    <div key={ix}>
        <b>{bundle.group}</b>
        <ul>
            {bundle.items.map((item, ix) => <li key={ix}>{item.item}</li>)}
        </ul>
    </div>
))}

Comments

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.