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

React类组件如何实现按钮按分类筛选商品功能

React类组件实现商品分类筛选方案

核心实现思路

因为筛选按钮和商品列表是两个独立子组件,筛选状态需要在二者之间同步,所以按照React类组件的状态提升原则,把筛选相关逻辑放在两个组件的共同父组件(通常是商品页的页面级组件)统一管理:

  • 父组件维护当前选中的分类状态,默认值为all
  • 父组件实现分类切换方法、商品过滤逻辑
  • 父组件把切换方法传给按钮组件绑定点击事件,把过滤后的商品列表传给商品组件渲染

分文件代码修改

1. 新增/修改共同父组件(示例命名为ShopPage.js)

这个组件是按钮组和商品列表的直接上层容器,负责统一管理状态:

import React, { Component } from 'react';
import { ProductList } from './productList';
import ButtonMenu from './ButtonMenu';
import Products from './products';

class ShopPage extends Component {
  constructor(props) {
    super(props);
    // 初始化状态:默认选中全部分类
    this.state = {
      selectedCategory: 'all'
    };
    // 绑定this指向,类组件自定义方法必须手动绑定
    this.handleCategoryChange = this.handleCategoryChange.bind(this);
  }

  // 分类切换处理函数
  handleCategoryChange(category) {
    this.setState({
      selectedCategory: category
    });
  }

  // 根据当前选中分类过滤商品
  getFilteredProducts() {
    const { selectedCategory } = this.state;
    if (selectedCategory === 'all') {
      return ProductList;
    }
    return ProductList.filter(item => item.category === selectedCategory);
  }

  render() {
    const filteredProducts = this.getFilteredProducts();
    const { selectedCategory } = this.state;
    return (
      <div className="shop-page">
        {/* 传选中状态和切换方法给按钮组 */}
        <ButtonMenu 
          currentCategory={selectedCategory}
          onCategoryChange={this.handleCategoryChange}
        />
        {/* 传过滤后的商品列表给商品渲染组件 */}
        <Products productList={filteredProducts} />
      </div>
    )
  }
}

export default ShopPage;

2. 修改ButtonMenu.js按钮组件

给每个按钮绑定点击事件,点击时触发父组件传过来的切换方法,还可以给当前选中的按钮加高亮样式:

import React, { Component } from 'react';

class ButtonMenu extends Component{
    constructor(props) {
      super(props);
      this.handleBtnClick = this.handleBtnClick.bind(this);
    }

    handleBtnClick(e) {
      // 拿到按钮上设置的分类value,传给父组件的回调
      const category = e.target.value;
      this.props.onCategoryChange(category);
    }

    render(){
        const { currentCategory } = this.props;
        return(
            <>
            <div className = "button Menu-container">
              <button 
                className = {`main-btn ${currentCategory === 'all' ? 'active' : ''}`} 
                value = "all"
                onClick={this.handleBtnClick}
              >ALL</button>
              <button 
                className = {`main-btn ${currentCategory === 'men' ? 'active' : ''}`} 
                value = "men"
                onClick={this.handleBtnClick}
              >Men</button>
              <button 
                className = {`main-btn ${currentCategory === 'women' ? 'active' : ''}`} 
                value = "women"
                onClick={this.handleBtnClick}
              >Women</button>
              <button 
                className = {`main-btn ${currentCategory === 'jerseys' ? 'active' : ''}`} 
                value = "jerseys"
                onClick={this.handleBtnClick}
              >Jerseys</button>
              <button 
                className = {`main-btn ${currentCategory === 'shirts' ? 'active' : ''}`} 
                value = "shirts"
                onClick={this.handleBtnClick}
              >Shirts</button>
              <button 
                className = {`main-btn ${currentCategory === 'accessories' ? 'active' : ''}`} 
                value = "accessories"
                onClick={this.handleBtnClick}
              >Accessories</button>
              <button 
                className = {`main-btn ${currentCategory === 'collectables' ? 'active' : ''}`} 
                value = "collectables"
                onClick={this.handleBtnClick}
              >Collectables</button>
            </div>
            </>
        )
    }
}

export default ButtonMenu; 

你可以自己在CSS里给.main-btn.active类加高亮样式,比如换背景色、加边框,区分选中状态。

3. 修改products.js商品列表组件

不再直接引用原始的ProductList遍历,改为接收父组件传过来的过滤后商品列表渲染:

import React, { Component } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCartPlus } from '@fortawesome/free-solid-svg-icons';

class Products extends Component{
    render(){
      const { productList } = this.props;
      return(
        <>
          <div className="container prod-cntr" >
            <div className = "row prod-row">
              {productList.map(element =>( 
                <div className = "col-lg-3 prod-col" key={element.id}>
                  <div className = "card card-container">
                    <img src = {element.image} alt ="product img" className="prod-img"/>
                    <div className="card-body">
                      <p className ="card-title">{element.product}</p>
                      <p className ="card-text">{element.description}</p>
                      <p className ="prod-price">{element.price}  <FontAwesomeIcon icon={faCartPlus} className="prod-carticon"/></p>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </>
      )
    }
}

export default Products;

注意事项

  • 类组件自定义的事件方法如果要访问this.setState,必须在构造函数里手动绑定this指向,或者用类字段箭头函数写法避免绑定
  • 不要在子组件里重复维护筛选状态,所有筛选逻辑统一收归父组件,避免出现状态不同步的bug
  • 原始商品数据ProductList作为常量数据源,不要直接修改,过滤时用filter方法返回新数组即可

内容的提问来源于stack exchange,提问作者madQuestions

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:54:24