Home > database >  Trying to filter an array of objects
Trying to filter an array of objects

Time:09-28

I have the following data:

[
    {
        category: 'FOOD',
        name: 'Canape Two',
        menuSections: [
            {
                name: 'Package',
            },
        ],
    },
    {
        category: 'FOOD',
        name: 'Canape One',
        menuSections: [
            {
                name: 'Package',
            },
        ],
    },
    {
        category: 'DRINK',
        name: 'Package One',
        menuSections: [
            {
                name: 'Drink Packages',
            },
        ],
    },
]

I want to be able to render the above data in React in the following way:

Package (Name of Section)
 - Canape One (Name of Menu Item)
 - Canape Two (Name of Menu Item)

Drink Packages (Name of Section
 - Package One (Name of Menu Item)

Each Menu Item might also have a subitem in the future. I don't have a clear idea on how to achieve this. Your help would be appreciated.

CodePudding user response:

The key is to get your data into a manageable state. Here I'm creating an object where the keys are the section name, and the value is an object containing the section name, and an array of items. You can then extract the values using Object.values to give you an array of objects that you can iterate over properly.

function Example({ menu }) {

  // `reduce` over the menu array to create an object
  // identified by a section name key. The object will
  // have a section name, and an array of items 
  const sections = menu.reduce((acc, item) => {
    const { menuSections: [{ name }], ...rest } = item;
    acc[name] = acc[name] || { name, items: [] };
    acc[name].items.push(rest);
    return acc;
  }, {});
  
  // Get the array of objects (values) from the
  // the sections object we created, and `map` over it
  // creating a new section for each object in the array
  return (
    <main>
      <section>
        {Object.values(sections).map(data => {
          return <Section section={data} />;
        })}
      </section>
    </main>
  );

}

// Add the name, and add a list. Iterate over the
// items array to produce a sorted list of items
function Section({ section }) {
  return (
    <section>
      <p className="sectionName">{section.name}</p>
      <ul>
        {section.items
          .sort((a, b) => a.name.localeCompare(b.name))
          .map(item => <Item item={item} />)}
      </ul>
    </section>
  );
}

// Returns a list item
function Item({ item }) {
  return <li>{item.name}</li>;
}

const menu=[{category:"FOOD",name:"Canape Two",menuSections:[{name:"Package"}]},{category:"FOOD",name:"Canape One",menuSections:[{name:"Package"}]},{category:"DRINK",name:"Package One",menuSections:[{name:"Drink Packages"}]}];

ReactDOM.render(
  <Example menu={menu} />,
  document.getElementById('react')
);
.sectionName { color: darkred; font-weight: 600; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Additional documentation

CodePudding user response:

First you need to create the json as per your requirement and then you need to render the data, as you can see the below code, here you can see the live example

import React, { useEffect, useState } from "react";

export default function App() {

  const [arr, setArr] = useState([]);

  const data = [
    {
      category: "FOOD",
      name: "Canape Two",
      menuSections: [
        {
          name: "Package",
        },
      ],
    },
    {
      category: "FOOD",
      name: "Canape One",
      menuSections: [
        {
          name: "Package",
        },
      ],
    },
    {
      category: "DRINK",
      name: "Package One",
      menuSections: [
        {
          name: "Drink Packages",
        },
      ],
    },
  ];

  useEffect(() => {
    let newArr = [];
    let duplicates = [];
    let obj = {};
    data.forEach((item) => {
      obj = {
        category: item.category,
        name: item.name,
      };
      item.menuSections.forEach((item1) => {
        if (!duplicates.includes(item1.name)) {
          duplicates.push(item1.name);
          obj = { ...obj, menuSection: item1.name };
        }
        newArr.push(obj);
      });
    });
    setArr(newArr);
  }, [])

  return (
    <div className="App">
      {arr.map((menu) => (
        <>
          <p>{menu.menuSection}</p>
          <p>-- {menu.name}</p>
        </>
      ))}
    </div>
  );
}
  • Related