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

React手风琴表格点击展开异常:如何定位指定触发组件?

解决React手风琴组件点击展开所有项的问题

你遇到的核心问题应该是用了一个全局状态变量来控制所有手风琴项的展开/收起状态——比如单个isHidden布尔值,导致点击任何一项都会触发全局状态切换,进而展开所有视图。下面给你两种常见的解决方案,按需选择:

方案一:用对象/数组跟踪每个项的独立状态

这种方式适合在父组件中集中管理所有项的展开状态,通过每个项的唯一标识(比如你API返回的Asset #)来精准控制:

1. 初始化状态

用对象存储每个项的展开状态,默认可以设为全部收起:

import { useState } from 'react';

// 假设你的API数据存在data变量里
const [hiddenStates, setHiddenStates] = useState(() => {
  // 初始化:所有项默认收起
  return data.reduce((acc, item) => ({
    ...acc,
    [item.assetId]: true // assetId是每个项的唯一标识,替换成你实际的字段
  }), {});
});

2. 编写精准切换的函数

这个函数接收当前项的唯一ID,只更新对应项的状态:

const toggleHidden = (assetId) => {
  setHiddenStates(prevState => ({
    ...prevState,
    [assetId]: !prevState[assetId] // 翻转当前项的状态
  }));
};

3. 渲染时绑定到对应项

在表格渲染中,给每个可点击的行绑定函数,并传入当前项的ID,同时根据状态控制展开内容的显示:

<Table striped bordered condensed hover>
  <thead>
    <tr>
      <th>Asset #</th>
      <th>Description</th>
      <th>Person</th>
    </tr>
  </thead>
  <tbody>
    {data.map(item => (
      <React.Fragment key={item.assetId}>
        {/* 可点击的表头行,触发toggle */}
        <tr onClick={() => toggleHidden(item.assetId)} style={{ cursor: 'pointer' }}>
          <td>{item.assetId}</td>
          <td>{item.description}</td>
          <td>{item.person}</td>
        </tr>
        {/* 展开的内容,根据当前项的状态控制显示 */}
        {!hiddenStates[item.assetId] && (
          <tr>
            <td colSpan={3}>
              {/* 这里放你要展开的详细内容,比如item的其他字段 */}
              <p>详细信息:{item.details}</p>
            </td>
          </tr>
        )}
      </React.Fragment>
    ))}
  </tbody>
</Table>

方案二:拆分为独立组件,每个组件自管理状态

如果你的手风琴项逻辑比较复杂,推荐把每个项拆成独立组件,让它自己管理展开状态,这样代码更模块化,也避免全局状态的干扰:

1. 创建AccordionItem组件

import { useState } from 'react';

const AccordionItem = ({ item }) => {
  // 每个组件自己的状态,互不影响
  const [isHidden, setIsHidden] = useState(true);

  const toggleHidden = () => {
    setIsHidden(!isHidden);
  };

  return (
    <React.Fragment>
      <tr onClick={toggleHidden} style={{ cursor: 'pointer' }}>
        <td>{item.assetId}</td>
        <td>{item.description}</td>
        <td>{item.person}</td>
      </tr>
      {!isHidden && (
        <tr>
          <td colSpan={3}>
            <p>详细信息:{item.details}</p>
          </td>
        </tr>
      )}
    </React.Fragment>
  );
};

2. 在父组件中使用

<Table striped bordered condensed hover>
  <thead>
    <tr>
      <th>Asset #</th>
      <th>Description</th>
      <th>Person</th>
    </tr>
  </thead>
  <tbody>
    {data.map(item => (
      <AccordionItem key={item.assetId} item={item} />
    ))}
  </tbody>
</Table>

关键注意点

  • 确保每个列表项有唯一的key(比如用assetId),React需要这个来正确识别和更新组件。
  • 如果你的API数据是异步获取的,初始化状态时要注意在数据加载完成后再设置(比如放在useEffect里)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:11:55