You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React商品多条件筛选:保留已有筛选值的实现求助

解决多条件商品筛选保留筛选值的问题

你的问题出在每次筛选时都直接从原始data中过滤,而不是基于当前已有的筛选条件叠加。要实现多条件同时筛选,需要跟踪所有活跃的筛选条件,然后根据这些条件统一过滤原始数据。

具体修改步骤:

  1. 用状态存储活跃筛选条件:创建一个状态对象保存当前选中的分类、品牌、颜色,而非直接存储过滤后的商品列表。
  2. 统一计算过滤结果:每次状态变化时,基于原始数据和所有活跃筛选条件计算最终商品列表。
  3. 更新筛选函数:点击筛选按钮时仅更新对应筛选条件的状态(支持切换选中/取消)。

修改后的完整代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 01:40:07