Kerry
Kerry

Reputation: 454

Loop & filter in JSX. How can I reduce the number of loops in this situation?

I am in kind of the tricky situation where I never been before.

This thing is the customer want to control what to show and what not to show in frontEnd from the server.

What they give me in api is something look like this

let control = [
             {
                "Title": "Products",
                "Enable": true,
                "Icon": "",
                "Value": "3"
            },
            {
                "Title": "Products",
                "Enable": true,
                "Icon": "",
                "Value": "3.1"
            },
            {
                "Title": "Bikes",
                "Enable": true,
                "Icon": "",
                "Value": "3.2"
            },
            {
                "Title": "Accessories",
                "Enable": true,
                "Icon": "",
                "Value": "3.3"
            },
            {
                "Title": "Components",
                "Enable": true,
                "Icon": "",
                "Value": "3.4"
            },
]

I told them to change the format but tell me back they can't change it. What they want is they want me to show the result accordingly to the Value of the return array. I have already done the filtering but my code involve lots of looping.

Here is my code

{navigationList.length > 1 &&
              navigationList.map((data) => {
                {
                  return (
                    data.Value === '3' && (
                      <List.AccordionGroup>
                        <List.Accordion
                          style={styles.accordionStyle}
                          title="Products"
                          id="1">
                          {navigationList.map((data) => {
                            {
                              return (
                                data.Value === '3.1' && (
                                  <TouchableOpacity
                                    style={styles.drawerItemBorder}
                                    onPress={() =>
                                      props.navigation.navigate('ProductScreen')
                                    }>
                                    <Text
                                      style={styles.drawerItemBorderTextTwo}>
                                      Go to Products
                                    </Text>
                                  </TouchableOpacity>
                                )
                              );
                            }
                          })}

                          {navigationList.map((data) => {
                            {
                              return (
                                data.Value === '3.2' && (
                                  <TouchableOpacity
                                    style={styles.drawerItemBorder}
                                    onPress={() =>
                                      props.navigation.navigate('BikesScreen')
                                    }>
                                    <Text
                                      style={styles.drawerItemBorderTextTwo}>
                                      Bikes
                                    </Text>
                                  </TouchableOpacity>
                                )
                              );
                            }
                          })}

                          {navigationList.map((data) => {
                            {
                              return (
                                data.Value === '3.3' && (
                                  <TouchableOpacity
                                    style={styles.drawerItemBorder}
                                    onPress={() =>
                                      props.navigation.navigate(
                                        'AccessoriesScreen',
                                      )
                                    }>
                                    <Text
                                      style={styles.drawerItemBorderTextTwo}>
                                      Accessories
                                    </Text>
                                  </TouchableOpacity>
                                )
                              );
                            }
                          })}

                          {navigationList.map((data) => {
                            {
                              return (
                                data.Value === '3.4' && (
                                  <TouchableOpacity
                                    style={styles.drawerItemBorder}
                                    onPress={() =>
                                      props.navigation.navigate(
                                        'ComponentScreen',
                                      )
                                    }>
                                    <Text
                                      style={styles.drawerItemBorderTextTwo}>
                                      Components
                                    </Text>
                                  </TouchableOpacity>
                                )
                              );
                            }
                          })}
                        </List.Accordion>
                      </List.AccordionGroup>
                    )
                  );
                }
              })}

So I want to know is what change I can make so that I can reduce the amount of looping here?

Upvotes: 1

Views: 75

Answers (1)

ray
ray

Reputation: 27265

Use reduce or some other mechanism to transform the data into the format you need, e.g. group the items by value:

const navigationList = [{
    "Title": "Products",
    "Enable": true,
    "Icon": "",
    "Value": "3"
  },
  {
    "Title": "Products",
    "Enable": true,
    "Icon": "",
    "Value": "3.1"
  },
  {
    "Title": "Bikes",
    "Enable": true,
    "Icon": "",
    "Value": "3.2"
  },
  {
    "Title": "Accessories",
    "Enable": true,
    "Icon": "",
    "Value": "3.3"
  },
  {
    "Title": "Components",
    "Enable": true,
    "Icon": "",
    "Value": "3.4"
  },
];

const grouped = navigationList.reduce((acc, item) => {
  acc[item.Value] = [...acc[item.Value] || [], item]
  return acc;
}, {})

console.log(grouped);

With the items grouped in this way you can then iterate them via Object.entries to render the items in a single loop:

const container = document.querySelector('.container');

const navigationList = [{
    "Title": "Products",
    "Enable": true,
    "Icon": "",
    "Value": "3"
  },
  {
    "Title": "Products",
    "Enable": true,
    "Icon": "",
    "Value": "3.1"
  },
  {
    "Title": "Bikes",
    "Enable": true,
    "Icon": "",
    "Value": "3.2"
  },
  {
    "Title": "Accessories",
    "Enable": true,
    "Icon": "",
    "Value": "3.3"
  },
  {
    "Title": "Components",
    "Enable": true,
    "Icon": "",
    "Value": "3.4"
  },
];

const grouped = navigationList.reduce((acc, item) => {
  acc[item.Value] = [...acc[item.Value] || [], item]
  return acc;
}, {})

Object.entries(grouped).map(([value, items]) => {
  heading(value);
  items.map(i => item(i.Title))
})





// --------------------------------------------
// You can ignore everything below. It's dom manipulation utility
// stuff because running react/jsx in SO snippets is a hassle.

function e (content, tag = 'div') {
  const elem = document.createElement(tag);
  elem.innerHTML = content;
  return elem;
}

function heading(value) {
  container.appendChild(e(value, 'h2'));
}
function item(value) {
  container.appendChild(e(value));
}
<div class="container"></div>

Upvotes: 1

Related Questions