skip to Main Content

I am new to React and have been trying to build a filter option.
i managed to filter single values for example category but if i select brand i lose the category value.. i am not sure how to filter multiple values keeping values: category + brand + color any help would be appreciated

heres my code: as you can see i am repeating code

import Products from './Products'
import data from '../data'
import { useState } from 'react'

const Main = () => {
    const [productData, setProductData] = useState(data)
    const productCat = [...new Set(data.map((product) => product.category))]
    const productBrand = [...new Set(data.map((product) => product.brand))]

    const filterCategory = (current) => {
        const newItem = data.filter((product) => {
        return product.category === current
        })
        setProductData(newItem)
    }

    const filterBrand = (current) => {
        const newItem = data.filter((product) => {
        return product.brand === current
        })
        setProductData(newItem)
    }

    const renderCategory = productCat.map((product, id) => {
        return (
        <button key={id} onClick={() => filterItem(product)}>
            {product}
        </button>
        )
    })

    const renderBrand = productBrand.map((product, id) => {
        return (
        <button key={id} onClick={() => filterBrand(product)}>
            {product}
        </button>
        )
    })

    return (
        <div>
        {renderCategory}
        {renderBrand}
        {productData.map((product) => (
            <Products
            img={product.image}
            key={product.id}
            name={product.name}
            category={product.category}
            brand={product.brand}
            price={product.price}
            color={product.color}
            />
        ))}
        </div>
    )
}

and this is my data structure:

const data = [
    {
        id: 1,
        category: 'Frames',
        brand: 'Alive',
        name: 'Badlands',
        price: 300,
        color: 'grey',
        image:
        'https://www.zenwebcart.com/user_data/images/products/alive/Badlands/alive-badlands_gry02.jpg'
    }
]

2

Answers


  1. You can filter by more than one criteria.

    
    const filterItem = (current) => {
        const newItem = data.filter((product) => {
          return product.category === current || product.brand === current; 
                
        });
        setProductData(newItem);
        return newItem
    
      };
    
    
    
    Login or Signup to reply.
  2. Explanation: As you want to add multiple filters you need to store all those filters somewhere and the filter out the data.
    Here, on the li element click the filter is saved in a state variable and an useEffect is in place to watch for any filters change and update the filtered product list accordingly

    import Products from './Products'
    import data from '../data'
    import { useEffect, useState } from 'react'
    
    const Main = () => {
        const [productData, setProductData] = useState(data)
        const [filters, setFilters] = useState({})
    
        const productCat = [...new Set(data.map((product) => product.category))]
        const productBrand = [...new Set(data.map((product) => product.brand))]
    
        useEffect(() => {
            const newData = data.filter((product) => {
            let filterable = false
            for (const filter in filters) filterable = filterable || filters[filter]
            if (!filterable) return true
    
            for (const filter in filters) {
                if (
                filters[filter] &&
                (product.category === filter || product.brand === filter)
                )
                return true
            }
    
            return false
            })
            setProductData(newData)
        }, [filters])
    
        const renderCategory = productCat.map((filter, id) => {
            return (
            <li
                key={id}
                onClick={() =>
                setFilters((state) => ({ ...state, [filter]: !state[filter] }))
                }
            >
                {filter}
            </li>
            )
        })
    
        const renderBrand = productBrand.map((filter, id) => {
            return (
            <li
                key={id}
                onClick={() =>
                setFilters((state) => ({ ...state, [filter]: !state[filter] }))
                }
            >
                {filter}
            </li>
            )
        })
    
        return (
            <div>
            {renderCategory}
            {renderBrand}
            {productData.map((product) => (
                <Products
                img={product.image}
                key={product.id}
                name={product.name}
                category={product.category}
                brand={product.brand}
                price={product.price}
                color={product.color}
                />
            ))}
            </div>
        )
    }
    
    export default Main
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search