React商品多条件筛选:保留已有筛选值的实现求助
解决多条件商品筛选保留筛选值的问题
你的问题出在每次筛选时都直接从原始data中过滤,而不是基于当前已有的筛选条件叠加。要实现多条件同时筛选,需要跟踪所有活跃的筛选条件,然后根据这些条件统一过滤原始数据。
具体修改步骤:
- 用状态存储活跃筛选条件:创建一个状态对象保存当前选中的分类、品牌、颜色,而非直接存储过滤后的商品列表。
- 统一计算过滤结果:每次状态变化时,基于原始数据和所有活跃筛选条件计算最终商品列表。
- 更新筛选函数:点击筛选按钮时仅更新对应筛选条件的状态(支持切换选中/取消)。
修改后的完整代码:
import Products from './Products' import data from '../data' import { useState, useMemo } from 'react' const Main = () => { // 存储活跃的筛选条件,初始为空 const [filters, setFilters] = useState({ category: null, brand: null, color: null }) // 提取唯一的分类、品牌、颜色选项 const productCat = [...new Set(data.map(product => product.category))] const productBrand = [...new Set(data.map(product => product.brand))] const productColors = [...new Set(data.map(product => product.color))] // 切换筛选条件(点击按钮时切换选中/取消) const toggleFilter = (type, value) => { setFilters(prev => ({ ...prev, [type]: prev[type] === value ? null : value })) } // 使用useMemo缓存过滤结果,避免不必要的重计算 const filteredProducts = useMemo(() => { return data.filter(product => { // 满足所有已选条件才保留商品 return ( (!filters.category || product.category === filters.category) && (!filters.brand || product.brand === filters.brand) && (!filters.color || product.color === filters.color) ) }) }, [filters]) // 渲染分类按钮,高亮选中项 const renderCategory = productCat.map((category, id) => ( <button key={id} onClick={() => toggleFilter('category', category)} style={{ backgroundColor: filters.category === category ? '#007bff' : 'white', color: filters.category === category ? 'white' : 'black', margin: '0 5px 5px 0', padding: '5px 10px', border: '1px solid #007bff', borderRadius: '4px', cursor: 'pointer' }} > {category} </button> )) // 渲染品牌按钮,高亮选中项 const renderBrand = productBrand.map((brand, id) => ( <button key={id} onClick={() => toggleFilter('brand', brand)} style={{ backgroundColor: filters.brand === brand ? '#007bff' : 'white', color: filters.brand === brand ? 'white' : 'black', margin: '0 5px 5px 0', padding: '5px 10px', border: '1px solid #007bff', borderRadius: '4px', cursor: 'pointer' }} > {brand} </button> )) // 渲染颜色按钮,高亮选中项 const renderColors = productColors.map((color, id) => ( <button key={id} onClick={() => toggleFilter('color', color)} style={{ backgroundColor: filters.color === color ? '#007bff' : 'white', color: filters.color === color ? 'white' : 'black', margin: '0 5px 5px 0', padding: '5px 10px', border: '1px solid #007bff', borderRadius: '4px', cursor: 'pointer' }} > {color} </button> )) return ( <div style={{ padding: '20px' }}> <div style={{ marginBottom: '20px' }}> <h3>分类筛选</h3> {renderCategory} </div> <div style={{ marginBottom: '20px' }}> <h3>品牌筛选</h3> {renderBrand} </div> <div style={{ marginBottom: '20px' }}> <h3>颜色筛选</h3> {renderColors} </div> <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: '20px' }}> {filteredProducts.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> </div> ) } export default Main
关键说明:
filters状态:集中管理所有筛选条件,每个条件初始为null(表示未筛选)。toggleFilter函数:点击按钮时切换对应条件的选中状态(选中则取消,未选中则设置)。useMemo优化:仅当filters变化时重新计算过滤结果,避免不必要的性能损耗。- 多条件叠加:
filter函数同时检查所有筛选条件,只有满足所有已选条件的商品才会被保留。 - 视觉反馈:按钮样式随选中状态变化,用户能清晰看到当前活跃的筛选条件。
修改后,无论先选分类还是品牌,所有筛选条件都会被保留,最终显示同时满足所有条件的商品。
内容的提问来源于stack exchange,提问作者bukke
相关产品推荐
相关产品推荐

