React中map渲染列表时onClick作用于所有项的解决方法
问题根源
你当前的实现把激活状态存在单个布尔值active中,所有遍历生成的列表项都共用这一个状态做样式判断,点击任意项触发状态更新后,所有项读取到的状态值同步变化,自然会一起切换样式,无法实现单一项的独立状态标记。另外原代码还存在JSX标签未闭合的语法问题。
修复方案
根据业务场景分两种实现方式:
- 单选模式:同一时间仅允许一个分类处于激活状态,适合分类互斥的筛选场景
- 多选模式:可同时选中多个分类,支持多条件叠加筛选场景
单选模式实现
将状态从布尔值改为存储当前激活项的唯一ID,渲染时逐项判断自身ID是否和激活ID匹配,匹配才加载激活样式:
const Product = ({categories}) => { // 存储当前激活的分类ID,初始值可设为null(默认无选中)或指定分类ID const [activeId, setActiveId] = useState(null) const handleCategoryClick = (categoryId) => { // 点击同一项时可设为null取消选中,不需要取消选中直接setActiveId(categoryId)即可 setActiveId(activeId === categoryId ? null : categoryId) } return ( <div className="flex flex-col"> <div className="pt-8 mx-4"> <h5 className="mx-4 text-2xl font-semibold">Kategoriler</h5> <ul className="flex"> {categories?.map((category)=>( <li onClick={() => handleCategoryClick(category.id)} className={ activeId === category.id ? "p-2 bg-yellow-200 shadow-lg m-2 transition duration-300 cursor-pointer" : "p-2 bg-white shadow-lg m-2 transition duration-300 cursor-pointer" } key={category.id} > {category.title} </li> ))} </ul> </div> </div> ) } export default Product;
多选模式实现
将状态改为存储所有激活项的ID数组,点击时判断当前项ID是否在数组中:已存在则移除(取消激活),不存在则加入(设为激活):
const Product = ({categories}) => { // 存储所有处于激活状态的分类ID const [activeIdList, setActiveIdList] = useState([]) const handleCategoryClick = (categoryId) => { setActiveIdList(prev => { return prev.includes(categoryId) ? prev.filter(id => id !== categoryId) : [...prev, categoryId] }) } return ( <div className="flex flex-col"> <div className="pt-8 mx-4"> <h5 className="mx-4 text-2xl font-semibold">Kategoriler</h5> <ul className="flex"> {categories?.map((category)=>( <li onClick={() => handleCategoryClick(category.id)} className={ activeIdList.includes(category.id) ? "p-2 bg-yellow-200 shadow-lg m-2 transition duration-300 cursor-pointer" : "p-2 bg-white shadow-lg m-2 transition duration-300 cursor-pointer" } key={category.id} > {category.title} </li> ))} </ul> </div> </div> ) } export default Product;
内容的提问来源于stack exchange,提问作者Ekrem Günden
相关产品推荐
相关产品推荐

