当我单击复选框时,过滤器工作,但当我再次单击时,过滤器不工作,并且复选框标记似乎也单独工作。我想在单击时,在复选框工作时,过滤此。需要为单个复选框创建布尔值吗?
const App = () => {
const [category, setCategory] = useState(["electronics","jewelery","men's clothing","women's clothing"]);
const [products, setProducts] = useState([
{"id":1,"title":"Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops","price":109.95,"category":"electronics", "rating":{"rate":3.9,"count":120}},
{"id":2,"title":"Mens Casual Premium Slim Fit T-Shirts ","price":22.3, "category":"men's clothing","rating":{"rate":4.1,"count":259}},
{"id":3,"title":"Mens Cotton Jacket","price":55.99, "category":"men's clothing","rating":{"rate":4.7,"count":500}},
{"id":4,"title":"Womens Dress","price":15.99, "category":"women's clothing" ,"rating":{"rate":2.1,"count":430}},
{"id":5,"title":"John Hardy Women's Legends Naga Gold & Silver Dragon Station Chain Bracelet","price":695, "category":"jewelery","rating":{"rate":4.6,"count":400}}
])
let [newProducts, setNewProducts] = useState([])
let [toCheck, setToCheck] = useState(true);
const filterProducts = (value) => {
setToCheck(!toCheck);
if (toCheck) {
newProducts = products
setNewProducts([...newProducts.filter((a) => a.category == value)])
}
}
return <div>
<div className='d-flex justify-content-evenly'>
{
category.map((elm, index) => {
return <div className="form-check ms-2" key={index}>
<input className="form-check-input" type="checkbox" value={elm} id="flexCheckDefault" onChange={(e) => filterProducts(e.target.value)}/>
<label className="form-check-label" htmlFor="flexCheckDefault">
{elm}
</label>
</div>
})
}
</div>
<div className='d-flex flex-wrap'>
{
(newProducts.length == 0 ? products : newProducts).map((prod) => {
return <div className='card m-3' style={{ width: "400px" }} key={prod.id}>
<div className='card-body'>
<p className='card-text'>Id: {prod.id}</p>
<h3 className='card-title'>Title: {prod.title}</h3>
<p className='card-text'>Price: {prod.price}</p>
<p className='card-text'>Category: {prod.category}</p>
<p className='card-text'>Rating: {prod.rating.rate}</p>
</div>
</div>
})
}
</div>
</div>
}
谢谢你
3条答案
按热度按时间bttbmeg01#
你可以通过
e.target.checked
而不是使用状态变量来获得复选框是否被选中。你也不需要附加一个值,你可以直接传递它,这并不重要。因为你要过滤多个元素,所以这个模式也不起作用。你需要保存所有的过滤器,这样你就可以删除一个,而在复选框未选中时保留其他的。我喜欢使用
Set
来实现这个目的。然后你就可以过滤该集合上的产品了。您也不需要为不变的常量使用状态变量。
另外,你的
id
和htmlFor
必须是唯一的,否则点击标签总是会选中第一个框。堆栈 lightning 战:https://stackblitz.com/edit/react-ts-9a9n67?file=App.tsx
mu0hgdu02#
简单解决方案(使用类别数组的更新数据模型)
mcvgt66p3#
以下是一个最小解决方案,它在不使用
useEffect
或更改category
和products
的情况下工作。可以在发布的代码中解决的几个问题:
1.每个
input
需要有一个唯一的id
,它与label
上的htmlFor
匹配,以便这对input
一起工作。1.当
filterProducts
设置一个新的状态值时,它不会在同一个块中获得更新的值。仅使用此事件来设置toCheck
中的过滤器。toCheck
的实值型别可以是[category]: Boolean
的对象,因此可以分别筛选每个分类,也可以组合筛选。1.原始的
products
可以在Map之前被过滤,因此不需要保持newProducts
的另一状态,或者修改products
数据。示例(现场演示:(第10页)