I am building a project and stacked. I am trying to implement a function which has to filter products by category and sort it in UI when user presses category button, so when I press button the array is updated but UI component does not work and I always have the same products. What I am doing wrong here? Here is my code:
import React, { useState, useEffect } from "react";
import "./ItemComponent.css";
function ItemsComponent() {
const [items, setItems] = useState([]);
const [search, setSearch] = useState("");
const [filterItems, setFilterItems] = useState(items);
// Fetching Data
useEffect(() => {
const fetchedData = async () => {
try {
const response = await fetch(`https://fakestoreapi.com/products`);
const data = await response.json();
console.log("Data", data);
setItems(data);
} catch (error) {
console.log(error);
}
};
fetchedData();
}, []);
const handleSubmit = (e) => {
e.preventDefault();
};
const filterProduct = (cat) => {
const updatedList = items.filter((item) => item.category === cat);
console.log("cat", cat);
console.log("updated", updatedList);
setFilterItems(updatedList);
};
return (
<>
<header>
<div className="overlay">
<h2>Welcome To E-Commerce Shop</h2>
</div>
<div className="search">
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Search..."
onChange={(e) => setSearch(e.target.value)}
/>
<button className="btn-light btn-search">Search</button>
</form>
</div>
<div className="categories">
<button
className="btn-dark category"
onClick={() => setFilterItems(items)}
>
All
</button>
<button
className="btn-dark category"
onClick={() => filterProduct("men's clothing")}
>
Men's Clothing
</button>
<button
className="btn-dark category"
onClick={() => filterProduct("women's clothing")}
>
Women's Closing
</button>
<button
className="btn-dark category"
onClick={() => filterProduct("jewelery")}
>
Jewelry
</button>
<button
className="btn-dark category"
onClick={() => filterProduct("electronics")}
>
Electronics
</button>
</div>
</header>
<div className="display-grid">
{Array.from(items)
.filter((value) => {
if (search === "") {
return value;
} else if (
value.title.toLowerCase().includes(search.toLowerCase())
) {
return value;
}
})
.map((item) => (
<div key={item.id}>
<div className="card">
<p className="title">{item.title}</p>
<img src={item.image} />
{/* <p className="description">{item.description}</p> */}
<p className="price">£ {item.price}</p>
<button className="btn-dark btn-buy">
<a href="#" className="btn-link">
Buy Now
</a>
</button>
</div>
</div>
))}
</div>
</>
);
}
export default ItemsComponent;
Here is I added screenshot to be more clear. Thank you in advance.
CodePudding user response:
You're not using your filterItems
array. You can fix it by using it in your display-grid
mapping:
<div className="display-grid">
{Array.from(filterItems)
.filter((value) => {
if (search === "") {
return value;
} else if (
value.title.toLowerCase().includes(search.toLowerCase())
) {
return value;
}
})
.map((item) => (
<div key={item.id}>
<div className="card">
<p className="title">{item.title}</p>
<img src={item.image} />
{/* <p className="description">{item.description}</p> */}
<p className="price">£ {item.price}</p>
<button className="btn-dark btn-buy">
<a href="#" className="btn-link">
Buy Now
</a>
</button>
</div>
</div>
))}
</div>
However, you might make things a bit more clear when you save your filter inside a state, instead of the filtered array created from the handler. You can then filter and search in one go as such:
const filterProduct = (cat) => setFilter(cat);
{Array.from(items).filter(item => !filter || item.category === filter)
.filter((value) => !search || value.title.toLowerCase().includes(search.toLowerCase()))
.map((item) => (
<div key={item.id}>
<div className="card">
<p className="title">{item.title}</p>
<img src={item.image} />
{/* <p className="description">{item.description}</p> */}
<p className="price">£ {item.price}</p>
<button className="btn-dark btn-buy">
<a href="#" className="btn-link">
Buy Now
</a>
</button>
</div>
</div>
))}
Here's a sandbox for it: https://codesandbox.io/s/elated-bartik-hq0cs7?file=/src/App.js
CodePudding user response:
in your arrow function "filterProduct" your are changing the "filterItems" with "setFilterItems" but in you are rendering your ui with "items" state.
Try to use "filterItems" to render your data