React中点击分类按钮后UI组件未更新的问题排查求助
电商分类筛选功能失效:点击按钮后UI未同步更新
我正在构建一个电商项目,想实现点击分类按钮按类别筛选商品并在UI展示的功能,但点击按钮后,控制台显示筛选后的数组已经更新,可页面上始终显示全部商品列表。附上我的代码和问题截图:
import React, { useState, useEffect } from "react"; import "./ItemComponent.css"; function ItemsComponent() { const [items, setItems] = useState([]); const [search, setSearch] = useState(""); const [filterItems, setFilterItems] = useState(items); // Fetching Data useEffect(() => { const fetchedData = async () => { try { const response = await fetch(`https://fakestoreapi.com/products`); const data = await response.json(); console.log("Data", data); setItems(data); } catch (error) { console.log(error); } }; fetchedData(); }, []); const handleSubmit = (e) => { e.preventDefault(); }; const filterProduct = (cat) => { const updatedList = items.filter((item) => item.category === cat); console.log("cat", cat); console.log("updated", updatedList); setFilterItems(updatedList); }; return ( <> <header> <div className="overlay"> <h2>Welcome To E-Commerce Shop</h2> </div> <div className="search"> <form onSubmit={handleSubmit}> <input type="text" placeholder="Search..." onChange={(e) => setSearch(e.target.value)} /> <button className="btn-light btn-search">Search</button> </form> </div> <div className="categories"> <button className="btn-dark category" onClick={() => setFilterItems(items)} > All </button> <button className="btn-dark category" onClick={() => filterProduct("men's clothing")} > Men's Clothing </button> <button className="btn-dark category" onClick={() => filterProduct("women's clothing")} > Women's Closing </button> <button className="btn-dark category" onClick={() => filterProduct("jewelery")} > Jewelry </button> <button className="btn-dark category" onClick={() => filterProduct("electronics")} > Electronics </button> </div> </header> <div className="display-grid"> {Array.from(items) .filter((value) => { if (search === "") { return value; } else if ( value.title.toLowerCase().includes(search.toLowerCase()) ) { return value; } }) .map((item) => ( <div key={item.id}> <div className="card"> <p className="title">{item.title}</p> <img src={item.image} /> {/* <p className="description">{item.description}</p> */} <p className="price">£ {item.price}</p> <button className="btn-dark btn-buy"> <a href="#" className="btn-link"> Buy Now </a> </button> </div> </div> ))} </div> </> ); } export default ItemsComponent;

问题根源
核心问题是UI渲染时始终使用原始的items数组,而非更新后的filterItems数组。虽然点击按钮后filterItems状态已正确更新,但页面渲染逻辑完全没用到这个状态,所以UI不会同步变化。
另外还有两个隐性问题:
filterItems初始化时依赖空数组items,数据获取后未同步更新filterItems,导致初始状态下filterItems为空。- 搜索功能仅基于
items过滤,未结合分类后的filterItems,会导致分类后搜索失效。
修复方案
- 渲染时改用
filterItems数组:将商品展示逻辑从Array.from(items)替换为Array.from(filterItems)。 - 同步初始
filterItems状态:添加useEffect监听items变化,数据获取完成后自动将filterItems设为全部商品。 - 整合搜索与分类逻辑:搜索过滤基于
filterItems,确保分类后搜索依然有效。
修复后的完整代码
import React, { useState, useEffect } from "react"; import "./ItemComponent.css"; function ItemsComponent() { const [items, setItems] = useState([]); const [search, setSearch] = useState(""); const [filterItems, setFilterItems] = useState([]); // Fetching Data useEffect(() => { const fetchedData = async () => { try { const response = await fetch(`https://fakestoreapi.com/products`); const data = await response.json(); console.log("Data", data); setItems(data); setFilterItems(data); // 数据获取后同步设置filterItems为全部商品 } catch (error) { console.log(error); } }; fetchedData(); }, []); const handleSubmit = (e) => { e.preventDefault(); }; const filterProduct = (cat) => { const updatedList = items.filter((item) => item.category === cat); console.log("cat", cat); console.log("updated", updatedList); setFilterItems(updatedList); }; return ( <> <header> <div className="overlay"> <h2>Welcome To E-Commerce Shop</h2> </div> <div className="search"> <form onSubmit={handleSubmit}> <input type="text" placeholder="Search..." onChange={(e) => setSearch(e.target.value)} /> <button className="btn-light btn-search">Search</button> </form> </div> <div className="categories"> <button className="btn-dark category" onClick={() => setFilterItems(items)} > All </button> <button className="btn-dark category" onClick={() => filterProduct("men's clothing")} > Men's Clothing </button> <button className="btn-dark category" onClick={() => filterProduct("women's clothing")} > Women's Clothing {/* 修复拼写错误:Closing -> Clothing */} </button> <button className="btn-dark category" onClick={() => filterProduct("jewelery")} > Jewelry </button> <button className="btn-dark category" onClick={() => filterProduct("electronics")} > Electronics </button> </div> </header> <div className="display-grid"> {Array.from(filterItems) // 改用filterItems渲染 .filter((value) => { if (search === "") { return value; } else if ( value.title.toLowerCase().includes(search.toLowerCase()) ) { return value; } return false; // 补全默认返回值 }) .map((item) => ( <div key={item.id}> <div className="card"> <p className="title">{item.title}</p> <img src={item.image} alt={item.title} /> {/* 添加alt属性优化可访问性 */} <p className="price">£ {item.price}</p> <button className="btn-dark btn-buy"> <a href="#" className="btn-link"> Buy Now </a> </button> </div> </div> ))} </div> </> ); } export default ItemsComponent;
额外修正说明
- 修复了按钮文本拼写错误:
Women's Closing→Women's Clothing,避免分类匹配失败。 - 给图片添加
alt属性,符合网页可访问性规范。 - 补全搜索过滤函数的默认返回值,避免逻辑漏洞。
内容的提问来源于stack exchange,提问作者zulfiya
相关产品推荐
相关产品推荐

