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

React中多个Collapsible组件实例疑似共享状态,点击第二个第一个展开原因是什么?

问题根源

你遇到的错位展开问题是多个因素共同导致的,按优先级排序如下:

  • 首要原因:Collapsible组件没有将传入的open属性绑定到内容区的显隐逻辑上,你当前代码里的Content、InnerContent完全没有根据open值调整展示状态,如果你的显隐逻辑依赖CSS选择器,DOM结构和选择器的匹配错误会导致状态命中到相邻组件的内容区。
  • 次要原因:使用数组下标作为列表key,如果FAQ列表后续有增删排序操作,会导致React复用错误的组件实例,出现状态错位;如果FAQ存在重复的question值,也会导致展开判断openFAQ === question命中多个组件。

解决方案

1. 补全Collapsible的内容显隐逻辑

根据你的交互需求选择两种实现方式:
不需要动画效果的条件渲染方案:

export const Collapsible = ({
  title,
  open,
  children,
  onClick,
  ...props
}: Props) => {
  return (
    <Container {...props}>
      <Toggle open={open} />
      <Title onClick={onClick}>{title}</Title>
      {/* 仅open为true时渲染内容 */}
      {open && <Content>
        <InnerContent>{children}</InnerContent>
      </Content>}
    </Container>
  );
};

需要动画效果的CSS控制方案:
给Content组件传递open属性,在样式中绑定显隐逻辑,以styled-components为例:

// 样式定义
const Content = styled.div<{open: boolean}>`
  height: 0;
  overflow: hidden;
  transition: all 0.3s ease;

  ${({open}) => open && `
    height: auto;
    padding: 12px 0;
  `}
`

// 组件调用
<Content open={open}>
  <InnerContent>{children}</InnerContent>
</Content>

2. 替换列表key值、改用唯一ID判断展开状态

避免question重复或数组变化导致的状态错位,建议给每个FAQ项增加唯一ID字段:

// 调整FAQS结构,增加唯一id
const FAQS = [
  {id: 'faq_001', question: '问题1', answer: '回答1'},
  {id: 'faq_002', question: '问题2', answer: '回答2'},
  // 其余项
]

// 状态逻辑调整为用ID判断
const [openFAQ, setOpenFAQ] = React.useState<string | null>(null);

const handleFAQClick = (id: string) => {
  setOpenFAQ(prev => prev === id ? null : id);
};

// 渲染时用id作为key和判断依据
return (
  FAQS.map(({ id, question, answer }) => (
    <Collapsible
      key={id}
      title={question}
      open={openFAQ === id}
      onClick={() => handleFAQClick(id)}
    >
      {answer}
    </Collapsible>
  ))
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:54:03