React手风琴组件:子项点击时isOpen状态无法切换的问题
问题解决思路
1. 点击无响应的核心原因
你给AccordionItem传了onClick和onKeyDown,但子组件里完全没用到这两个事件——可点击的accordion__item-label标签上没有绑定这些事件,所以点击时根本不会触发toggleAccordion函数。
2. 基础修复:让点击生效
先修改AccordionItem组件,把接收的事件绑定到可点击区域,同时补上标题渲染(不然用户不知道点哪里):
const AccordionItem = ({ title, text, itemId, isOpen, onClick, onKeyDown }) => { const contentRef = useRef(null) return ( <div className={`accordion__item ${isOpen ? 'accordion__item-label--expanded' : ''}`} data-kontent-item-id={itemId}> <div className='accordion__item-label js-accordion__item-label' tabIndex={0} onClick={onClick} onKeyDown={onKeyDown} > {title} </div> <div className='accordion__item-content js-accordion__item-content' ref={contentRef} > <div className='accordion__item-content-wrapper' dangerouslySetInnerHTML={{ __html: text }} /> </div> </div> ) }
3. 优化:实现单个子项独立展开(可选但更实用)
你现在用单个布尔值isOpen,会导致所有子项同时展开/收起,这不是手风琴组件的常规行为。改成记录当前展开的子项ID,就能实现独立控制:
修改父组件的状态和切换逻辑:
// 初始状态设为null,表示没有展开的子项 const [openItemId, setOpenItemId] = useState(null) const toggleAccordion = (itemId) => { // 点击已展开的子项就关闭,否则展开它 setOpenItemId(prevId => prevId === itemId ? null : itemId) } return ( <div className='grid'> {enableSearch && searchComponents} {accordionData.length > 0 ? ( <section className='accordion' data-kontent-item-id={id}> {title && <h2 className='accordion__title'>{title}</h2>} {accordionData.map((item, key) => item.title && ( <AccordionItem key={key} title={item.title} text={item.text} itemId={item.id} onClick={() => toggleAccordion(item.id)} onKeyDown={(e) => handleKeyDown(e, item.id)} // 键盘事件也要传递子项ID isOpen={openItemId === item.id} /> ) )} </section> ) : ( enableSearch && ( <div className='mt-8' dangerouslySetInnerHTML={{ __html: noResultsText }} /> ) )} </div> )
这样修改后,点击每个子项的标题就能独立展开/收起对应的内容了。
内容的提问来源于stack exchange,提问作者mop333
相关产品推荐
相关产品推荐

