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

React Hooks手风琴组件点击时全部区块同步切换问题:如何实现单个区块独立展开收起?

如何让React Accordion单个区块独立展开/收起?

这个问题很常见——你现在用了一个全局的open布尔状态来控制所有折叠面板,所以点击任何一个按钮都会触发同一个状态更新,导致所有面板同步展开或收起。咱们只需要把状态改成跟踪单个/多个独立的区块标识,就能实现每个面板独立切换的功能。

解决方案思路

我们可以用两种方式实现:

  1. 单面板展开:同一时间只允许一个面板展开,用状态记录当前展开的面板ID
  2. 多面板展开:允许同时展开多个面板,用对象记录每个面板的展开状态

下面针对你的代码给出具体修改方案:

方案1:单面板展开(同一时间仅一个面板打开)

把原来的单个open状态,改成记录当前展开的剧集ID:

export const HomePage: React.FC<IProps> = () => {
  // 用null表示没有面板展开,存储当前展开的剧集ID
  const [expandedEpisodeId, setExpandedEpisodeId] = useState<number | null>(null);

  return (
    <div>
      {data.characters.results.map((character: { id: number, name: string, image: string; episode: any; }, index: number) => (
        <div key={character.id}>
          <CharacterHeading>{character.name}</CharacterHeading>
          <CharacterImage src={character.image} alt={character.name} />
          {character.episode.map((char: { name: string; air_date: string; episode: string; characters: any, id: number; }) => (
            <div key={char.id}>
              {char.name} {char.air_date} {char.episode}
              <AccordionButton 
                open={expandedEpisodeId === char.id} 
                onClick={() => {
                  // 如果当前面板已经展开,就收起;否则展开当前面板
                  setExpandedEpisodeId(expandedEpisodeId === char.id ? null : char.id);
                }}
              >
                Check all characters
              </AccordionButton>
              <EpisodeListSection open={expandedEpisodeId === char.id}>
                {char.characters.map((ep: { id: number, name: string; image: string; }, index: number) => (
                  <EpisodeInfo key={ep.id}>
                    <EpisodeInfoBlock>
                      <EpisodeName>{ep.name}</EpisodeName>
                      <EpisodeImage src={ep.image} alt={ep.name} />
                    </EpisodeInfoBlock>
                  </EpisodeInfo>
                ))}
              </EpisodeListSection>
            </div>
          ))}
        </div>
      ))}
    </div>
  );
};

方案2:多面板展开(允许同时打开多个面板)

如果需要支持同时展开多个面板,可以用对象来存储每个剧集的展开状态:

export const HomePage: React.FC<IProps> = () => {
  // 用对象记录每个剧集的展开状态,key是剧集ID,value是布尔值
  const [expandedEpisodes, setExpandedEpisodes] = useState<Record<number, boolean>>({});

  return (
    <div>
      {data.characters.results.map((character: { id: number, name: string, image: string; episode: any; }, index: number) => (
        <div key={character.id}>
          <CharacterHeading>{character.name}</CharacterHeading>
          <CharacterImage src={character.image} alt={character.name} />
          {character.episode.map((char: { name: string; air_date: string; episode: string; characters: any, id: number; }) => (
            <div key={char.id}>
              {char.name} {char.air_date} {char.episode}
              <AccordionButton 
                open={expandedEpisodes[char.id] || false} 
                onClick={() => {
                  // 切换当前剧集的展开状态
                  setExpandedEpisodes(prev => ({
                    ...prev,
                    [char.id]: !prev[char.id]
                  }));
                }}
              >
                Check all characters
              </AccordionButton>
              <EpisodeListSection open={expandedEpisodes[char.id] || false}>
                {char.characters.map((ep: { id: number, name: string; image: string; }, index: number) => (
                  <EpisodeInfo key={ep.id}>
                    <EpisodeInfoBlock>
                      <EpisodeName>{ep.name}</EpisodeName>
                      <EpisodeImage src={ep.image} alt={ep.name} />
                    </EpisodeInfoBlock>
                  </EpisodeInfo>
                ))}
              </EpisodeListSection>
            </div>
          ))}
        </div>
      ))}
    </div>
  );
};

为什么这样改?

原来的open状态是全局的布尔值,所有面板都依赖同一个状态判断是否展开。修改后,每个面板的展开状态由自身的唯一ID来控制:

  • 方案1中,只有ID匹配当前expandedEpisodeId的面板会展开
  • 方案2中,每个面板的展开状态独立存储在对象里,互不影响

你可以根据需求选择其中一种方案,两种都能解决所有面板同步切换的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:12:41