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

React中如何在array map遍历中正确实现collapsible可折叠内容?

问题根因

你的所有列表条目共用了同一个全局布尔状态showCollapsible,没有和对应条目做绑定,只要状态变更所有条目都会同步执行显隐逻辑,这个问题和你添加的key属性无关:key的作用是帮助React做列表元素的重渲染diff优化,不负责状态的隔离绑定。另外你当前把key加在了button元素上是错误用法,key需要加在map方法返回的最外层根元素上才能生效。

解决方案

方案1:仅允许同时展开1个条目(匹配你描述的需求)

将状态修改为存储当前展开条目的唯一id,点击时更新为当前点击条目的id即可:

import { useState } from "react";

const App = () => {
  // 初始值为null表示无展开条目,存储当前展开条目的id
  const [activeId, setActiveId] = useState(null);

  const myDatas = [
    {
      id: 1,
      fullName: "John Doe",
      age: 28,
      status: "On Duty",
    },
    {
      id: 2,
      fullName: "Jane Doe",
      age: 27,
      status: "Rest",
    },
    {
      id: 3,
      fullName: "James Doe",
      age: 32,
      status: "Take a leave",
    },
  ];

  return (
    <div>
      {myDatas.map((data) => {
        return (
          // key放在map返回的最外层元素上,用条目自身的id比index更可靠
          <div key={data.id}>
            <p>{data.fullName}</p>
            <p>{data.age}</p>
            <button
              onClick={() => {
                // 如果点击的是当前已展开的条目,就收起,否则切换为当前点击的条目
                setActiveId(activeId === data.id ? null : data.id)
              }}
            >
              Status
            </button>
            {/* 仅当前条目的id和激活id匹配时展示status */}
            {activeId === data.id && <div>{data.status}</div>}
          </div>
        );
      })}
    </div>
  );
};

export default App;

方案2:允许多个条目同时展开

如果需要支持同时展开多个条目,可以将状态改为存储每个条目的展开状态映射:

import { useState } from "react";

const App = () => {
  // 用对象存储每个id对应条目的展开状态
  const [showMap, setShowMap] = useState({});

  const myDatas = [
    {
      id: 1,
      fullName: "John Doe",
      age: 28,
      status: "On Duty",
    },
    {
      id: 2,
      fullName: "Jane Doe",
      age: 27,
      status: "Rest",
    },
    {
      id: 3,
      fullName: "James Doe",
      age: 32,
      status: "Take a leave",
    },
  ];

  return (
    <div>
      {myDatas.map((data) => {
        return (
          <div key={data.id}>
            <p>{data.fullName}</p>
            <p>{data.age}</p>
            <button
              onClick={() => {
                setShowMap(prev => ({
                  ...prev,
                  [data.id]: !prev[data.id]
                }))
              }}
            >
              Status
            </button>
            {showMap[data.id] && <div>{data.status}</div>}
          </div>
        );
      })}
    </div>
  );
};

export default App;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 21:09:03