Object.entries return an empty Array

Viewed 137

I am following a MERN ecommerce tutorial which I stuck at the point where we want to filter the product by color & size

here is Mongo model

   const productSchema = new mongoose.Schema(
  {
    title: {
      type: String,
      required: true,
    },
    description: {
      type: String,
      required: true,
    },
    image: {
      type: String,
      required: true,
    },
    categories: {
      type: Array,
    },
    size: {
      type: Array,
    },
    color: {
      type: Array,
    },
    price: {
      type: Number,
      required: true,
    },
    countInStock: {
      type: Number,
      required: true,
    },
  },
  {
    timestamps: true,
  }
)

const Product = mongoose.model('Product', productSchema)

This is get allProduct endpoint (express.js backend)

 const getAllProducts = asyncHandler(async (req, res) => {
  //We need to give user query functionality
  const qNew = req.query.new //we find by latest product
  const qCategory = req.query.category //we can find by category
  try {
    let products
    if (qNew) {
      products = await Product.find().sort({ createdAt: -1 }).limit(1)
    } else if (qCategory) {
      products = await Product.find({
        categories: {
          $in: [qCategory], //inside the categories Array
        },
      })
    } else {
      products = await Product.find({})
    }

    res.status(200).json(products)
  } catch (err) {
    res.status(404)
    throw new Error('No User Found')
  }
})

This what we set the route in App.jsx

<Route path="/products/:category" element={<ProductList/>}></Route>

In the productList we create filter keyword and pass them as props to Product (React frontend)

    const ProductList = () => {
  const location = useLocation()
const category = location.pathname.split("/")[2]//get the category key word

const [filters,setFilter] = useState({})
//when change color or size it will change state
const [sort,setSort] = useState("newest")

const handleFilter = (e) =>{
  const value = e.target.value;//value is whatever we enter 
  //whether it's color or size it will change state
  setFilter({
    ...filters,//when I select color and size togather both will inside same Array 
[e.target.name]:value,//if we select red from option the filter value is red, if select L size from size option then filter value is L
  })
}

    return (
        <Container>
            <Navbar/>
            <Announcement/>
             <Title>Dresses</Title>
            <FilterContainer>
                <Filter>
                    <FilterText>Filter Products:</FilterText>
            <Select name="color" onChange={handleFilter}>
            <Option disabled >
              Color
            </Option>
            <Option>white</Option>
            <Option>black</Option>
            <Option>red</Option>
            <Option>blue</Option>
            <Option>yellow</Option>
            <Option>green</Option>
          </Select>
          <Select name="size" onChange={handleFilter}>
            <Option disabled >
              Size
            </Option>
            <Option>XS</Option>
            <Option>S</Option>
            <Option>M</Option>
            <Option>L</Option>
            <Option>XL</Option>
          </Select >
                </Filter>
                <Filter>
                <FilterText>Filter Products:</FilterText>
            <Select onChange={(e) =>setSort(e.target.value)}>
            <Option value="Newest">Newest</Option>
            <Option value="asc">Price (asc)</Option>
            <Option value="desc">Price (desc)</Option>
          </Select>
                </Filter>
            </FilterContainer>
            <Products category={category} filters={filters} sort={sort}/>
            {/* category key word / filter keyword size & color / sort keyword Newst */}
            <Footer/>
        </Container>
    )
}

And we make HTTP request in Product page, I pretty sure there have an object return back from endpoint inside res.data and updated in products(useState) but after the Object.entries filtering logic all it return was empty Array in filteredProducts(useState)

    const Products = ({category,filters,sort}) => {
const [products,setProducts] = useState([]);
const [filteredProducts,setFilteredProducts] = useState([]);

useEffect(() =>{//category key word
const getProducts = async ()=>{
    try{
    const res = await axios.get(category ? `http://localhost:5000/api/products?category=${category}` : "http://localhost:5000/api/products")
    setProducts(res.data)//data won't go in state imediately

    }catch(err)
    {
console.log(err)
    }
}
getProducts()
//untill here the products still have the data inside
},[category,setProducts])

useEffect(() =>{
category && setFilteredProducts(
    products.filter((item) =>
    Object.entries(filters).every(([key, value]) =>
      item[key].includes(value)
    )
  )
    
)
},[category,products,filters,setFilteredProducts])


    return (
        <Container>

            {category ?
            filteredProducts.map((item) =>
            <Product item={item} key={item._id} />) :
            products
            .slice(0,8)
            .map((item) => <Product item={item}/>)
            //whenever you use map you need to indicate unique key
           
    }
        </Container>
    )
}

Anyone can help me with this issue ? I really want to solve this problem.

1 Answers

I solved the problem!! I didn't set the corresponding category in my MongoDB so that's why when it goes to filtering logic it couldn't find the data to send back to frontend

Related