React中点击按钮筛选API获取的商品数据的实现方法咨询
实现方案
核心逻辑
你只需要在渲染商品列表前,根据选中的筛选项对原始products数组做前端过滤,再遍历过滤后的结果渲染即可,修改成本很低,具体修改步骤如下:
步骤1:优化筛选状态管理
原来的两个布尔状态扩展性较差,我们替换为单个状态记录当前选中的商品类型,默认展示全部商品:
// 删掉原来的mugSelected、shirtSelected两个状态,替换为下面的代码 const [selectedType, setSelectedType] = useState('all'); // 可选值: all / mug / shirt
步骤2:修改筛选按钮的点击和样式逻辑
调整两个按钮的点击事件和类名判断,支持点击切换、再次点击取消筛选回到全部:
<div className="product-type-filter"> <button className={selectedType === 'mug' ? "clicked" : null} onClick={() => setSelectedType(prev => prev === 'mug' ? 'all' : 'mug')} > Mug </button> <button className={selectedType === 'shirt' ? "clicked" : null} onClick={() => setSelectedType(prev => prev === 'shirt' ? 'all' : 'shirt')} > Shirt </button> </div>
步骤3:新增商品过滤逻辑
在渲染商品列表前,新增过滤规则,得到符合条件的商品数组:
// 放在return之前即可 const filteredProducts = selectedType === 'all' ? products : products?.filter(product => product.itemType === selectedType) || [];
步骤4:替换渲染的数据源
把原来遍历products的代码,替换为遍历过滤后的filteredProducts:
{/* 原来的products.map改成filteredProducts.map */} {filteredProducts.map((product) => ( <Product key={product.added} product={product}></Product> ))}
完整修改后代码参考
import React, { useEffect, useState } from "react"; import Product from "../components/sub-components/Product"; import LoadingBox from "../components/sub-components/LoadingBox"; import MessageBox from "../components/sub-components/MessageBox"; import { useDispatch, useSelector } from "react-redux"; import { listProducts } from "../actions/productActions"; import ReactPaginate from "react-paginate"; export default function HomeScreen() { const dispatch = useDispatch(); const productList = useSelector((state) => state.productList); const { loading, error, products } = productList; const [currentPage, setCurrentPage] = useState(1); const [pageCount, setpageCount] = useState(0); // 替换原筛选状态 const [selectedType, setSelectedType] = useState('all'); useEffect(() => { dispatch(listProducts(currentPage)); // dispatch(countProducts()); }, [dispatch, currentPage]); const handlePageClick = (data) => { setCurrentPage(data.selected + 1); // scroll to the top window.scrollTo(0, 0) }; // 新增过滤逻辑 const filteredProducts = selectedType === 'all' ? products : products?.filter(product => product.itemType === selectedType) || []; return ( <div className="container"> <div className="row"> <div className="col-lg-6 col-md-12 col-sm-12 col-xs-12"> <h2 className="title">Products</h2> <div className="product-type-filter"> {/* 修改后的筛选按钮 */} <button className={selectedType === 'mug' ? "clicked" : null} onClick={() => setSelectedType(prev => prev === 'mug' ? 'all' : 'mug')} > Mug </button> <button className={selectedType === 'shirt' ? "clicked" : null} onClick={() => setSelectedType(prev => prev === 'shirt' ? 'all' : 'shirt')} > Shirt </button> </div> <div className="products"> <div className="row"> <div> {loading ? ( <LoadingBox></LoadingBox> ) : error ? ( <MessageBox variant="danger">{error}</MessageBox> ) : ( <div className="row center"> {/* 替换为过滤后的数组 */} {filteredProducts.map((product) => ( <Product key={product.added} product={product}></Product> ))} </div> )} </div> </div> </div> <ReactPaginate previousLabel={"Prev"} nextLabel={"Next"} pageCount={40} marginPagesDisplayed={4} pageRangeDisplayed={1} onPageChange={handlePageClick} containerClassName={"pagination justify-content-center"} pageClassName={"page-item"} pageLinkClassName={"page-link"} previousClassName={"page-item"} previousLinkClassName={"page-link"} nextClassName={"page-item"} nextLinkClassName={"page-link"} breakClassName={"page-item"} breakLinkClassName={"page-link"} activeClassName={"active"} /> </div> </div> </div> ); }
补充说明
如果你的listProducts接口是后端分页的(即每次只返回当前页的10/20条数据,不是全量商品),那么前端筛选只能过滤当前页的内容,要实现全量筛选需要把selectedType作为参数传给接口,由后端返回对应类型的分页数据即可。
内容的提问来源于stack exchange,提问作者breking bed
相关产品推荐
相关产品推荐

