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

Reactstrap手风琴点击一个全部折叠,需实现独立控制

解决Reactstrap手风琴同步展开/折叠问题

问题根源是所有CompanyAccordion组件共享父组件的同一个open状态,点击任意一个都会修改这个全局状态,导致所有手风琴同步变化。以下是两种可行解决方案:

方案一:子组件独立维护状态(推荐,适合独立工作需求)

让每个CompanyAccordion自己管理展开状态,不需要父组件传递状态,这样每个手风琴的状态完全独立:

修改CompanyAccordion组件

import { useState } from 'react';
import { Accordion, AccordionBody, AccordionHeader, AccordionItem } from 'reactstrap';
import styled from 'styled-components';
import ReactSwitch from 'react-switch';
import { ReactComponent as EmiratesPost } from 'assets/img/logos/emirates-post.svg'

const CompanyAccordion = ({toggleChecked, setToggleChecked}) => {
  // 子组件内部维护自身的展开状态
  const [open, setOpen] = useState(false);

  const toggle = () => {
    setOpen(!open);
  };

  return (
    <Wrapper>
      <SubWrapper>
        <EmiratesPost style={{maxWidth:"100%"}} />
        <SwitchComponent>
          <ReactSwitch onChange={()=>setToggleChecked(!toggleChecked)} checked={toggleChecked}/>
        </SwitchComponent>
      </SubWrapper>
      <AccordionWrapper>
        <Accordion open={open} toggle={toggle}>
          <AccordionItem style={{border:"0px"}} >
            <AccordionHeader>
              Accordion Item
            </AccordionHeader>
            <AccordionBody>
              <strong>This is the item's accordion body.</strong>
              You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
            </AccordionBody>
          </AccordionItem > 
        </Accordion>
      </AccordionWrapper>
    </Wrapper>
  );
}

修改SellerShipping组件

移除不需要的open状态及传递:

import { useState } from 'react';

const SellerShipping = () => {
  const [toggleChecked, setToggleChecked] = useState(false)
  return (
    <Wrapper>
        <TagLine>Shipping and delivery</TagLine>
        <SearchBar>
          <SearchBox />
          <SuggestButton>suggest a company</SuggestButton>
        </SearchBar>
        <AccordionWrapper className=''>
            <CompanyAccordion toggleChecked={toggleChecked} setToggleChecked={setToggleChecked} />
            <CompanyAccordion toggleChecked={toggleChecked} setToggleChecked={setToggleChecked} />
        </AccordionWrapper>
    </Wrapper>
  )
}

方案二:父组件管理多手风琴状态(适合需要父组件控制的场景)

如果需要父组件知晓每个手风琴的展开状态,可以用对象存储每个手风琴的状态:

修改SellerShipping组件

import { useState } from 'react';

const SellerShipping = () => {
  // 用对象存储每个手风琴的展开状态,key为手风琴ID
  const [openStates, setOpenStates] = useState({
    "1": false,
    "2": false
  });
  const [toggleChecked, setToggleChecked] = useState(false)

  const handleToggle = (id) => {
    setOpenStates(prev => ({
      ...prev,
      [id]: !prev[id]
    }));
  }

  return (
    <Wrapper>
        <TagLine>Shipping and delivery</TagLine>
        <SearchBar>
          <SearchBox />
          <SuggestButton>suggest a company</SuggestButton>
        </SearchBar>
        <AccordionWrapper className=''>
            <CompanyAccordion 
              toggleChecked={toggleChecked} 
              setToggleChecked={setToggleChecked} 
              open={openStates["1"]} 
              toggle={() => handleToggle("1")} 
              toggleid="1" 
            />
            <CompanyAccordion 
              toggleChecked={toggleChecked} 
              setToggleChecked={setToggleChecked} 
              open={openStates["2"]} 
              toggle={() => handleToggle("2")} 
              toggleid="2" 
            />
        </AccordionWrapper>
    </Wrapper>
  )
}

修改CompanyAccordion组件

直接使用父组件传递的open状态和toggle方法:

import { Accordion, AccordionBody, AccordionHeader, AccordionItem } from 'reactstrap';
import styled from 'styled-components';
import ReactSwitch from 'react-switch';
import { ReactComponent as EmiratesPost } from 'assets/img/logos/emirates-post.svg'

const CompanyAccordion = ({open, toggle, toggleid, toggleChecked, setToggleChecked}) => {
  return (
    <Wrapper>
      <SubWrapper>
        <EmiratesPost style={{maxWidth:"100%"}} />
        <SwitchComponent>
          <ReactSwitch onChange={()=>setToggleChecked(!toggleChecked)} checked={toggleChecked}/>
        </SwitchComponent>
      </SubWrapper>
      <AccordionWrapper>
        <Accordion open={open} toggle={toggle}>
          <AccordionItem style={{border:"0px"}} >
            <AccordionHeader targetId={toggleid}>
              Accordion Item {toggleid}
            </AccordionHeader>
            <AccordionBody accordionId={toggleid}>
              <strong>This is the {toggleid} item's accordion body.</strong>
              You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
            </AccordionBody>
          </AccordionItem > 
        </Accordion>
      </AccordionWrapper>
    </Wrapper>
  );
}

关于之前移状态仍无效的说明

如果之前尝试将状态移到子组件但问题依旧,大概率是Accordion组件的open属性没有绑定到子组件内部的状态,或者toggle逻辑仍在使用父组件的状态变量,导致状态同步问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:33:23