Creating a Reactive Restaurant Grid with Filtering Using React and Tailwind CSS
Tags: react, javascript, tutorial, programming
Published: 2024-01-21 11:54:00

![](https://miro.medium.com/v2/resize:fit:1013/1*m1p1deJccGQHG61vzZ2odg.png align="left")

In the realm of web development, creating a delightful user experience is paramount. One way to achieve this is by presenting information in a visually appealing and easily navigable manner. In this article, we'll explore a React code snippet that accomplishes just that - showcasing top-rated menu items with dynamic filtering.

# **The Code Structure**

Let's break down the provided React code:

# `App.js`

```plaintext
import React from "react";
import Food from "./components/Food";

function App() {
  return (
    <div>
      <Food />
    </div>
  );
}

export default App;
```

This is the entry point where the `Food` component is rendered. The `Food` component is where the main functionality resides.

# `Food.js`

```plaintext
import React, { useState } from 'react';

const data = [
  {
    id: 1,
    name: 'Double Cheeseburger',
    category: 'burger',
    image:
      'https://images.unsplash.com/photo-1607013251379-e6eecfffe234?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8YnVyZ2Vyc3xlbnwwfHwwfHw%3D&auto=format&fit=crop&w=1400&q=60',
    price: '$$$$',
  },
  {
    id: 2,
    name: 'Bacon Cheeseburger',
    category: 'burger',
    image:
      'https://images.unsplash.com/photo-1553979459-d2229ba7433b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTh8fGJ1cmdlcnN8ZW58MHx8MHx8&auto=format&fit=crop&w=1400&q=60',
    price: '$',
  },
  {
    id: 3,
    name: 'Mushroom Burger',
    category: 'burger',
    image:
      'https://images.unsplash.com/photo-1608767221051-2b9d18f35a2f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTV8fGJ1cmdlcnN8ZW58MHx8MHx8&auto=format&fit=crop&w=1400&q=60',
    price: '$$',
  },
  {
    id: 4,
    name: 'Loaded Burger',
    category: 'burger',
    image:
      'https://images.unsplash.com/photo-1568901346375-23c9450c58cd?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8YnVyZ2Vyc3xlbnwwfHwwfHw%3D&auto=format&fit=crop&w=1400&q=60',
    price: '$$$',
  },
  {
    id: 5,
    name: 'Feta & Spinnach',
    category: 'pizza',
    image:
      'https://images.unsplash.com/photo-1593560708920-61dd98c46a4e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8OHx8cGl6emF8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$$',
  },
  {
    id: 6,
    name: 'Supreme Pizza',
    category: 'pizza',
    image:
      'https://images.unsplash.com/photo-1604382355076-af4b0eb60143?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8N3x8cGl6emF8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$$$',
  },
  {
    id: 7,
    name: 'Meat Lovers',
    category: 'pizza',
    image:
      'https://images.unsplash.com/photo-1628840042765-356cda07504e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTh8fHBpenphfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=800&q=60',
    price: '$$$$',
  },
  {
    id: 8,
    name: 'Cheese Pizza',
    category: 'pizza',
    image:
      'https://images.unsplash.com/photo-1548369937-47519962c11a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8OXx8Y2hlZXNlJTIwcGl6emF8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$',
  },
  {
    id: 9,
    name: 'Kale Salad',
    category: 'salad',
    image:
      'https://images.unsplash.com/photo-1515543237350-b3eea1ec8082?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8M3x8c2FsYWQlMjBjZWFzYXJ8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$$',
  },
  {
    id: 10,
    name: 'Ceasar Salad',
    category: 'salad',
    image:
      'https://images.unsplash.com/photo-1546793665-c74683f339c1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8c2FsYWQlMjBjZWFzYXJ8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$$$',
  },
  {
    id: 11,
    name: 'Loaded Salad',
    category: 'salad',
    image:
      'https://images.unsplash.com/photo-1540420773420-3366772f4999?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8c2FsYWR8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$$$$',
  },
  {
    id: 12,
    name: 'Fruit Salad',
    category: 'salad',
    image:
      'https://images.unsplash.com/photo-1564093497595-593b96d80180?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8ZnJ1aXQlMjBzYWxhZHxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=800&q=60',
    price: '$',
  },
  {
    id: 13,
    name: 'Wings',
    category: 'chicken',
    image:
      'https://images.unsplash.com/photo-1567620832903-9fc6debc209f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8Y2hpY2tlbiUyMGZvb2R8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$$',
  },
  {
    id: 14,
    name: 'Baked Chicken',
    category: 'chicken',
    image:
      'https://images.unsplash.com/photo-1594221708779-94832f4320d1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Nnx8Y2hpY2tlbiUyMGZvb2R8ZW58MHx8MHx8&auto=format&fit=crop&w=800&q=60',
    price: '$$$$',
  },
  {
    id: 15,
    name: 'Chicken Tenders',
    category: 'chicken',
    image:
      'https://images.unsplash.com/photo-1562967914-608f82629710?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fGNoaWNrZW4lMjBmb29kfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=800&q=60',
    price: '$',
  },
  {
    id: 16,
    name: 'Chicken Kabob',
    category: 'chicken',
    image:
      'https://images.unsplash.com/photo-1603360946369-dc9bb6258143?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTN8fGNoaWNrZW4lMjBmb29kfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=800&q=60',
    price: '$$$',
  },
];

const Food = () => {
  const [foods, setFoods] = useState(data);

  //   Filter Type burgers/pizza/etc
  const filterType = (category) => {
    setFoods(
      data.filter((item) => {
        return item.category === category;
      })
    );
  };

  //   Filter by price
  const filterPrice = (price) => {
    setFoods(
      data.filter((item) => {
        return item.price === price;
      })
    );
  };

  return (
    <div className='max-w-[1640px] m-auto px-4 py-12'>
      <h1 className='text-orange-600 font-bold text-4xl text-center'>
        Top Rated Menu Items
      </h1>

      {/* Filter Row */}
      <div className='flex flex-col lg:flex-row justify-between'>
        {/* Fliter Type */}
        <div>
          <p className='font-bold text-gray-700'>Filter Type</p>
          <div className='flex justfiy-between flex-wrap'>
            <button
              onClick={() => setFoods(data)}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              All
            </button>
            <button
              onClick={() => filterType('burger')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              Burgers
            </button>
            <button
              onClick={() => filterType('pizza')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              Pizza
            </button>
            <button
              onClick={() => filterType('salad')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              Salads
            </button>
            <button
              onClick={() => filterType('chicken')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              Chicken
            </button>
          </div>
        </div>

        {/* Filter Price */}
        <div>
          <p className='font-bold text-gray-700'>Filter Price</p>
          <div className='flex justify-between max-w-[390px] w-full'>
            <button
              onClick={() => filterPrice('$')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              $
            </button>
            <button
              onClick={() => filterPrice('$$')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              $$
            </button>
            <button
              onClick={() => filterPrice('$$$')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              $$$
            </button>
            <button
              onClick={() => filterPrice('$$$$')}
              className='m-1 border-orange-600 text-orange-600 hover:bg-orange-600 hover:text-white'
            >
              $$$$
            </button>
          </div>
        </div>
      </div>

      {/* Display foods */}
      <div className='grid grid-cols-2 lg:grid-cols-4 gap-6 pt-4'>
        {foods.map((item, index) => (
          <div
            key={index}
            className='border shadow-lg rounded-lg hover:scale-105 duration-300'
          >
            <img
              src={item.image}
              alt={item.name}
              className='w-full h-[200px] object-cover rounded-t-lg'
            />
            <div className='flex justify-between px-2 py-4'>
              <p className='font-bold'>{item.name}</p>
              <p>
                <span className='bg-orange-500 text-white p-1 rounded-full'>
                  {item.price}
                </span>
              </p>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default Food;
```

This component manages the state of displayed foods and provides filtering functionality based on type and price. It also renders a visually appealing grid of food items with their details.

# **Understanding the Functionality**

# **Filtering by Type**

The `filterType` function filters the displayed foods based on the selected category (burger, pizza, etc.). Each button associated with a category triggers this filter when clicked.

```plaintext
<button onClick={() => filterType('burger')} className='...'>
  Burgers
</button>
```

# **Filtering by Price**

Similarly, the `filterPrice` function filters foods based on the selected price range. Each button associated with a price range triggers this filter when clicked.

```plaintext
<button onClick={() => filterPrice('$')} className='...'>
  $
</button>
```

# **Displaying Food Items**

The code efficiently maps through the filtered `foods` array and displays each item in a visually appealing card format.

```plaintext
{foods.map((item, index) => (
  <div key={index} className='...'>
    {/* ... (Food item details) ... */}
  </div>
))}
```

# **Conclusion**

This React code provides a robust foundation for displaying and dynamically filtering top-rated menu items. By understanding and customizing this code, developers can create engaging and user-friendly interfaces for showcasing a variety of content. Whether you're building a restaurant menu or any other categorized content display, this React setup can be a valuable starting point. Happy coding!