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

如何使用useState仅修改当前被点击的Accordion卡片样式

问题根源

你当前所有卡片共用同一个布尔类型的clicked状态,只要状态变更,所有卡片的样式判断条件都会同步更新,才会出现点击任意卡片全部变色的问题。

修复方案

根据业务需求分为两种实现场景:


场景1:每次仅允许一张卡片处于激活状态(常规手风琴效果)

将state改为存储当前激活卡片的唯一标识(建议用item的业务唯一id,无id可暂用map遍历的index代替),点击时仅更新当前标识的匹配状态即可。
代码示例:

// 初始值为null,代表无激活卡片
const [activeId, setActiveId] = useState(null);

<div className="row">
  {items &&
    items.map((item, index) => (
      {/* 必须给遍历项加唯一key,这里如果item有id优先用item.id */}
      <div className="col-md-6 faqpadding" key={item.id ?? index}>
        <Accordion
          className="cardHeight"
          style={{
            backgroundColor: activeId === item.id ? "#fff" : "#0e2043",
            boxShadow: "0px 4px 22px 9px rgba(0, 0, 0, 0.17)",
            border: "1px solid #919191",
            color: activeId === item.id ? "#0e2043" : "#E3AB50",
            padding: "20px",
          }}
        >
          <AccordionSummary
            expandIcon={<ExpandMoreIcon />}
            {/* 动态修改无障碍属性,避免重复 */}
            aria-controls={`panel${item.id}-content`}
            id={`panel${item.id}-header`}
            onClick={() => {
              // 如果点击的是当前激活卡片,就取消激活,否则设为当前卡片id
              setActiveId(activeId === item.id ? null : item.id)
            }}
          >
            <Typography
              className={classes.heading}
              style={{ textAlign: "center" }}
            >
              {item.Title}
            </Typography>
          </AccordionSummary>
          <AccordionDetails>
            <Typography>{item.Content}</Typography>
          </AccordionDetails>
        </Accordion>
      </div>
    ))}
</div>

场景2:允许多张卡片同时激活

将state改为存储对象格式的状态映射,key为卡片唯一标识,value为当前卡片的激活状态,点击时仅修改对应key的状态即可。
代码示例:

// 初始值为空对象,所有卡片默认未激活
const [activeMap, setActiveMap] = useState({});

<div className="row">
  {items &&
    items.map((item, index) => (
      <div className="col-md-6 faqpadding" key={item.id ?? index}>
        <Accordion
          className="cardHeight"
          style={{
            backgroundColor: activeMap[item.id] ? "#fff" : "#0e2043",
            boxShadow: "0px 4px 22px 9px rgba(0, 0, 0, 0.17)",
            border: "1px solid #919191",
            color: activeMap[item.id] ? "#0e2043" : "#E3AB50",
            padding: "20px",
          }}
        >
          <AccordionSummary
            expandIcon={<ExpandMoreIcon />}
            aria-controls={`panel${item.id}-content`}
            id={`panel${item.id}-header`}
            onClick={() => {
              setActiveMap(prev => ({
                ...prev,
                [item.id]: !prev[item.id]
              }))
            }}
          >
            <Typography
              className={classes.heading}
              style={{ textAlign: "center" }}
            >
              {item.Title}
            </Typography>
          </AccordionSummary>
          <AccordionDetails>
            <Typography>{item.Content}</Typography>
          </AccordionDetails>
        </Accordion>
      </div>
    ))}
</div>

注意事项

原来的代码中AccordionSummary的aria-controls和id属性为固定值,多卡片重复会导致无障碍属性冲突,上述代码中已改为和item唯一标识绑定的动态值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 21:39:00