A way to split up a map in react?

Not the best title, but I have another project where its like a menu for a site. Right now, I have just two components. One is the menu which will render the other component and the other component is menu items. The menu items will use an api to get the items table and then map out the items in the component. However, is there a way to split up the results of a map? Lets say that I only want the drinks in the menu item to be displayed under a heading of “drinks” or burgers listed out a heading of “burgers”. I tried searching, but not sure if there is a way to do that

EDIT: Here is an edit to the original question, I found a way to filter the results based on a property of the row. This is just dummy data that I am using to test right now but here is the code

import React, { useState } from 'react';

function Items() {
  const [items, setItems] = useState([]);
  const array = [
    { coffee: "Americano", size: "Medium", price: 50, description: "medium coffee" },
    { coffee: "Espressoododod", size: "large", price: 20, description: "large coffee" },
    { coffee: "Espresso", size: "large", price: 20, description: "large coffee" },
    { coffee: "Espressoooo", size: "large", price: 20, description: "large coffee" },
    { coffee: "Espresso", size: "small", price: 20, description: "large coffee" }
  ];

  return (
    <div>
      <h1>Drinks</h1>
      {array
        .filter(array => {
          return (
            array.size === 'large'
          );
        })
      .map((arr) => (
        <div className="foodItem"> <p> Name: {arr.coffee}</p> <p>Size {arr.size}</p> <p> Price {arr.price}</p> <p>{arr.description}</p></div>
      ))}
    </div>
  );
}
export default Items;

So with the code it will only map those who size =“large”. Not sure if this is “best practice” or necessarily a bad thing, but what if I added another map so that it looks like this now

import React, { useState } from 'react';

function Items() {
  const [items, setItems] = useState([]);
  const array = [
    { coffee: "Americano", size: "small", price: 50, description: "medium coffee", category: "drinks" },
    { coffee: "Espressoododod", size: "large", price: 20, description: "large coffee", category: "starters" },
    { coffee: "Espresso", size: "large", price: 20, description: "large coffee", category: "drinks" },
    { coffee: "Espressoooo", size: "large", price: 20, description: "large coffee", category: "starters"},
    { coffee: "Espresso", size: "small", price: 20, description: "large coffee", category: "drinks" }
  ];

  return (
    <div>
     
      {array
        .filter(array => {
          return (
            
            array.size === 'large'
          );
        })
      .map((arr) => (
        <>
        <h1></h1><div className="foodItem"> <p> Name: {arr.coffee}</p> <p>Size {arr.size}</p> <p> Price {arr.price}</p> <p>{arr.description}</p></div>
        </>
      ))}

{array
        .filter(array => {
          return (
            array.size === 'small'
          );
        })
      .map((arr) => (
        <>
        <h1></h1><div className="foodItem"> <p> Name: {arr.coffee}</p> <p>Size {arr.size}</p> <p> Price {arr.price}</p> <p>{arr.description}</p></div>
        </>
      ))}
  </div>
  );
}
export default Items;

It does what I want, but not sure if this is a good thing to use or not. Not sure if there is a rule against multiple maps

I was going to suggest you filter it as well. There shouldn’t be anything wrong with doing so.

One option might be to move it out of the JSX and maybe add a useMemo to it so it only re-runs when it has to (not sure where you are getting the API data in the component tree).

1 Like

I am afraid the dummy data passed in don’t work properly, because if you want to use map function, you should assign a key value which must be unique. Besides, I suggest you can share the status value of size between componets to split the results. So I changed your code snippet a little bit:

const array = [
{
id: 1,
coffee: “Americano”,
size: “Medium”,
price: 50,
description: “medium coffee”,
},
{
id: 2,
coffee: “Espressoododod”,
size: “large”,
price: 20,
description: “large coffee”,
},
{
id: 3,
coffee: “Espresso”,
size: “large”,
price: 20,
description: “large coffee”,
},
{
id: 4,
coffee: “Espressoooo”,
size: “large”,
price: 20,
description: “large coffee”,
},
{
id: 5,
coffee: “Espresso”,
size: “small”,
price: 20,
description: “large coffee”,
},
];

const MenuItems = ({drinkSize}) => {
const largeCoffee = array.filter((item) => item.size === drinkSize);

return (


Large Size













{largeCoffee.map((item) => (







))}

ID coffee size price Description
{item.id} {item.coffee} {item.size} {item.price} {item.description}

</div>

);
};

export default MenuItems;

function App() {
const [drinkSize, setDrinkSize] = useState(‘’);

return (




</div>

);
}

export default App;

1 Like

So the code will probably change when I start trying to get the api in here. Right now, I am just looking of a good way to get make an api call for that specific table. The results will then be saved in setItems state. Then I will filter based on the category of the menu, so instead of saying arr.size === “large” it will look like items.category === “starters”. The code in my original post was just mainly so I knew that it was getting displayed and grouped together correctly.

Thanks for the reply, but I am not wanting to use setState in the above example. Eventually, I will when I add the code for the api call and will save the results in setItems. The code above was just dummy code that was testing to make sure that the items will be grouped together based on the size. That code will change to match the data in my table, but as of right now it does group correctly.

It looks like you’ve duplicated a loooot of code. Why not make a helper function that accepts a size, and returns the corresponding JSX.

Then you could reduce all that down to something like this:

return (
  <div>
    {renderCoffeeListings('large')}
    {renderCoffeeListings('small')}
  </div>
)

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.