'Nested Array.prototype.map

so I'm kind of stuck on this one.

I am trying to render a cart object with product names, prices and quantity.

Each product may have its own array of objects of product options.

What I'm stuck on is rendering the product options with their respective product option group.

So say, a meal may have toppings and beverages as option groups and the individual toppings or beverages themselves are the options.

Here's an image output of the render:

cart render image output

Here's the code for the product options rendering part:

{
  !!item["productOptions"].length && (
    <>
      <List sx={{ mt: "-16px", pt: 0, pl: 1 }}>
        {Object.keys(cartOptgroups).map((keyId, i) => (
          <>
            <ListItem sx={{ pb: "2px", pt: "2px" }}>
              <Grid container>
                <Grid item xs={2}>
                  <div></div>
                </Grid>
                <Grid item xs={8}>
                  <Typography sx={{ pr: "8px" }} variant="body2">
                    {cartOptgroups[keyId] + ":"}
                  </Typography>
                  {item["productOptions"].map((option, index) => (
                    <>
                      {option.groupId == keyId && (
                        <>
                          <Chip
                            sx={{ mt: "4px", mr: "4px" }}
                            variant="filled"
                            size="small"
                            color="default"
                            label={option.optionName}
                          />
                        </>
                      )}
                    </>
                  ))}
                </Grid>
                <Grid item xs={2}>
                  <div></div>
                </Grid>
              </Grid>
            </ListItem>
          </>
        ))}
      </List>
    </>
  );
}

So as the cart is rendered I am basically building an object of the possible option groups:

{1: Accompagnement, 2: Extras}

And I have an array of option objects:

[{
    groupId: groupId,
    groupName: groupName,
    optionId: optionId,
    optionName: optionName,
    optionPrice: optionPrice,
}]

Then I map through the groups object and render the group names. I then map through the options array themselves and compare if the associated groupId of the option itself in the options array is equal to the id inside the groups object and render the option if it is equal.

So the problem is that since I am going through the groups object first then the options array, I will render the group name regardless if there are options that match. But if I go through the options array first, I will render the group name multiple times. Since the groups object is built independently, it does not contain any way for me to compare with the options array.

I feel like this could be solved by including data when I build the groups object so that I can compare it to the options array, or maybe I could set variables while rendering? Could anyone point me in the right direction? Any help would be greatly appreciated. Thanks!



Solution 1:[1]

In the end, I restructured the way the product options are added to the cart:

So when I check or uncheck boxes, my child component will pass the same option object like before:

let option = {
                groupId: groupId,
                groupName: groupName,
                optionId: optionId,
                optionName: optionName,
                optionPrice: optionPrice,
            }

The parent function receives the option object and builds the object structure to be appended to the add to cart item from the child component:

let object = {
                groupId: option.groupId,
                groupName: option.groupName,
                groupOptions: [{
                                optionId: option.optionId,
                                optionName: option.optionName,
                                optionPrice: option.optionPrice
                            }]
            };

Before doing that, it checks if the group already exists, if it does then it just appends the option object into groupOptions:

let currentOption = {
                optionId: option.optionId,
                optionName: option.optionName,
                optionPrice: option.optionPrice
            }

Now I just render it back out as a simple nested array.prototype.map and everything works good.

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 jasnlink