DEV Community

Idan Bakal
Idan Bakal

Posted on • Edited on

Building a High-Performance Dynamic Product Filter Component in React and Tailwind CSS

In modern e-commerce applications, user experience is everything. Users expect to filter through hundreds of products instantly without irritating page reloads. A lagging or poorly designed filter UI can directly impact conversion rates.

In this tutorial, we will build a production-ready, highly responsive Dynamic Product Filter Component from scratch using React (with state optimization) and Tailwind CSS for slick, modern styling.


Step 1: The Product Data Structure

First, let's define our mock product database structure. Create a file named data.js or keep it inside your component:


export const PRODUCTS_DATA = [
  { id: 1, name: "UltraFit Running Shoes", category: "Footwear", price: 120, rating: 4.8 },
  { id: 2, name: "Pro-Grip Training Gloves", category: "Accessories", price: 35, rating: 4.5 },
  { id: 3, name: "AirWeave Sports Hoodie", category: "Apparel", price: 75, rating: 4.6 },
  { id: 4, name: "Pulse Smart Fitness Watch", category: "Electronics", price: 240, rating: 4.9 },
  { id: 5, name: "Apex Cushion Sneakers", category: "Footwear", price: 150, rating: 4.2 },
  { id: 6, name: "Thermal Hydro Flask", category: "Accessories", price: 45, rating: 4.7 }
];

export const CATEGORIES = ["All", "Footwear", "Apparel", "Accessories", "Electronics"];

Step 2: Implementing the Core Filter Component

We will utilize the useMemo hook from React to ensure maximum performance. This caches the filtered results and only recalculates them when our criteria actually change, preventing unnecessary re-renders.

Here is the complete code for ProductFilter.jsx:


import React, { useState, useMemo } from 'react';

const PRODUCTS_DATA = [
{ id: 1, name: "UltraFit Running Shoes", category: "Footwear", price: 120, rating: 4.8 },
{ id: 2, name: "Pro-Grip Training Gloves", category: "Accessories", price: 35, rating: 4.5 },
{ id: 3, name: "AirWeave Sports Hoodie", category: "Apparel", price: 75, rating: 4.6 },
{ id: 4, name: "Pulse Smart Fitness Watch", category: "Electronics", price: 240, rating: 4.9 },
{ id: 5, name: "Apex Cushion Sneakers", category: "Footwear", price: 150, rating: 4.2 },
{ id: 6, name: "Thermal Hydro Flask", category: "Accessories", price: 45, rating: 4.7 }
];

const CATEGORIES = ["All", "Footwear", "Apparel", "Accessories", "Electronics"];

export default function ProductFilter() {
const [searchQuery, setSearchQuery] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All');
const [maxPrice, setMaxPrice] = useState(300);
const [sortBy, setSortBy] = useState('featured');

const filteredProducts = useMemo(() => {
let result = [...PRODUCTS_DATA];

if (searchQuery.trim() !== '') {
  result = result.filter(p => p.name.toLowerCase().includes(searchQuery.toLowerCase()));
}
if (selectedCategory !== 'All') {
  result = result.filter(p => p.category === selectedCategory);
}
result = result.filter(p => p.price <= maxPrice);

if (sortBy === 'price-low') result.sort((a, b) => a.price - b.price);
else if (sortBy === 'price-high') result.sort((a, b) => b.price - a.price);
else if (sortBy === 'rating') result.sort((a, b) => b.rating - a.rating);

return result;
Enter fullscreen mode Exit fullscreen mode

}, [searchQuery, selectedCategory, maxPrice, sortBy]);

return (

      <h1>Discover Products</h1>
      <p>Filter and find exactly what you need in real-time.</p>





          Search
           setSearchQuery(e.target.value)}
            placeholder="Search products..."
            className="w-full px-4 py-2 bg-slate-50 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
          /&gt;



          Category

            {CATEGORIES.map(category =&gt; (
               setSelectedCategory(category)}
                className="px-3 py-1.5 text-xs font-medium rounded-lg transition"
              &gt;
                {category}

            ))}





            Max Price
            <span>${maxPrice}</span>

           setMaxPrice(Number(e.target.value))}
            className="w-full h-2 bg-slate-100 rounded-lg appearance-none cursor-pointer accent-blue-600"
          /&gt;



          Sort By
           setSortBy(e.target.value)}
            className="w-full px-3 py-2 bg-slate-50 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
          &gt;
            Featured
            Price: Low to High
            Price: High to Low
            Highest Rated






          {filteredProducts.map(product =&gt; (


                <span>
                  {product.category}
                </span>
                <h3>{product.name}</h3>


                <span>${product.price}</span>
                <span>★ {product.rating}</span>


          ))}
Enter fullscreen mode Exit fullscreen mode

);
}

Conclusion

By leveraging optimization hooks, we ensure that sorting and filtering are computed only when dependencies update, maintaining a rock-solid user experience. This architecture scales perfectly for e-commerce needs.

Top comments (0)