如何在React的map循环中通过onClick函数修改选中项的颜色?
解决React Map循环中点击元素切换背景色的问题
你的核心需求是点击元素时,通过比对_id和keyType与hasClip数组的匹配情况,切换元素背景色。原代码的问题在于没有使用React状态管理,hasClip是静态常量,点击后无法触发UI更新。以下是修正方案:
关键问题分析
hasClip定义为普通常量,修改后不会触发组件重渲染handleFill仅执行了匹配检查,没有实际修改数据并更新状态
修正后的完整代码
import { useState } from 'react'; import styled from 'styled-components'; const data = [ { keyType: "category", filtered: [ { _id: 1, name: "Stocks", paramValue: "stocks" }, { _id: 19, name: "Commodities", paramValue: "commodities" }, ], }, { keyType: "topics", filtered: [ { _id: 8, name: "Preferred stocks", paramValue: "preferred-stocks" }, { _id: 24, name: "Stocks", paramValue: "stocks" }, ], }, ]; const initialHasClip = [ { _id: 1, keyType: "category", name: "Stocks", paramValue: "stocks" }, { _id: 8, keyType: "topics", name: "Preferred stocks", paramValue: "preferred-stocks", }, ]; const Par = () => { // 将hasClip转为状态变量,实现数据驱动UI const [hasClip, setHasClip] = useState(initialHasClip); // 检查当前项是否在hasClip中 const checkKeyword = (category, id) => { return hasClip.some( (item) => item._id === id && item.keyType === category ); }; // 处理点击逻辑:匹配则移除,不匹配则添加 const handleFill = (category, item) => { const isExist = checkKeyword(category, item._id); if (isExist) { // 移除匹配项 setHasClip(prev => prev.filter( clipItem => clipItem._id !== item._id || clipItem.keyType !== category )); } else { // 添加新项 setHasClip(prev => [...prev, { ...item, keyType: category }]); } }; return ( <> {data.map((category) => ( <div key={category.keyType}> <h1>{category.keyType}</h1> {category.filtered.map((item) => ( <StyledComp key={`${category.keyType}-${item._id}`} // 更安全的key,避免同_id不同keyType冲突 onClick={() => handleFill(category.keyType, item)} $clip={checkKeyword(category.keyType, item._id)} > {item.name} </StyledComp> ))} </div> ))} </> ); }; const StyledComp = styled.div` width: 150px; height: 50px; margin: 8px; background-color: ${({ $clip }) => ($clip ? "red" : "transparent")}; border: 1px solid #ccc; display: flex; align-items: center; justify-content: center; cursor: pointer; `; export default Par;
核心修改点说明
- 状态化管理hasClip:使用
useState将initialHasClip转为响应式状态,修改后自动触发组件重渲染 - 完善handleFill逻辑:
- 点击时先检查当前项是否已存在于
hasClip - 存在则通过
filter移除匹配项,不存在则通过扩展运算符添加新项
- 点击时先检查当前项是否已存在于
- 优化key值:使用
${category.keyType}-${item._id}作为key,避免不同分类下相同_id的元素key冲突 - 调整样式:把
none改为transparent,避免元素边框消失,同时增加基础样式提升交互体验
内容的提问来源于stack exchange,提问作者stellum
相关产品推荐
相关产品推荐

