'How to group items under specific parent item in React?

I have a groups API which has id and group_name field. There is another training API which gives me training_name and training_group_id. Every training in training API is linked to a group.

Present Output on UI - Group 1 - Training 1 | Group 2 - Training 2 | Group 2 - Training 3 | Group 2 - Training 4

Is there a way I can show by grouping the trainings which has common group_name to appear under one group_name and not repeat as shown in above output?

Expected Output on UI - Group 1 - Training 1 | Group 2 - Training 2, Training 3, Training 4

Code -

function TileViewNew() {
  const { currentUserTrainings, trainingGroups } = useContext(MyContext);

  const renderTrainingGroupName = training => {
    const trainingGroupName = trainingGroups.find(group => {
      return group.id === training;
    });
    return trainingGroupName.group_name;
  };

  return (
    <Grid>
      {currentUserTrainings.map(({ training_name, training_group }) => (
        <>
          <Grid>
            <strong>{renderTrainingGroupName(training_group)}</strong>
          </Grid>
          {training_name}
        </>
      ))}
    </Grid>
  );
}

export default TileViewNew;


Solution 1:[1]

You can basically transform the data you get from api in this fashion

const currentUserTrainings = [{training_name: 'Training 1',training_group_id: 1,},{training_name: 'Training 2',training_group_id: 2,},{training_name: 'Training 3',training_group_id: 2,},{training_name: 'Training 4',training_group_id: 2,},];
const trainingGroups = [{group_name: 'Group 1',group_id: 1,},{group_name: 'Group 2',group_id: 2,},];

// group trainings by group id

let transformedTraining = currentUserTrainings.reduce((acc,curr) => {
  let id = curr.training_group_id
  acc[id] = acc[id] || []
  acc[id].push(curr)
  return acc
}, {})

// loop over groups to show final output

trainingGroups.forEach((curr)=>{
  let name = curr.group_name
  let id  = curr.group_id
  let trainings = transformedTraining[id]?.map(v => v.training_name).join(',')
  console.log(name, trainings)
})

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Code Maniac