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

如何在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;

核心修改点说明

  1. 状态化管理hasClip:使用useState将initialHasClip转为响应式状态,修改后自动触发组件重渲染
  2. 完善handleFill逻辑:
    • 点击时先检查当前项是否已存在于hasClip
    • 存在则通过filter移除匹配项,不存在则通过扩展运算符添加新项
  3. 优化key值:使用${category.keyType}-${item._id}作为key,避免不同分类下相同_id的元素key冲突
  4. 调整样式:把none改为transparent,避免元素边框消失,同时增加基础样式提升交互体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:09:30