Creating a Reactive Restaurant Grid with Filtering Using React and Tailwind CSS
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
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
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.
<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.
<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.
{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!
Subscribe to my newsletter
Read articles from ryad directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by