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
相关产品推荐
相关产品推荐

