React中useRef无法获取动态div ID,返回重复ID的问题
解决React手风琴组件的展开控制问题
我看了你的代码,问题主要出在单个useRef无法存储多个元素引用和单个isOpen状态无法区分多个手风琴项这两点上,咱们一步步来修正:
核心问题分析
- useRef的误用:你用了一个
divIdref来绑定所有循环生成的div,这会导致ref最终只会指向最后一个渲染的div,所以每次获取到的ID都是最后一个项的索引,自然没法区分不同的手风琴。 - 状态设计不合理:单个
isOpen布尔值无法同时控制多个手风琴的展开/关闭,应该用一个状态来记录当前活跃的手风琴索引,这样就能精准控制哪一个展开。 - 事件参数传递错误:你的
onClick={(indexNo) => toggle2(indexNo)}其实把点击事件对象传给了toggle2,而不是你想要的索引,这会导致判断逻辑完全失效。
修改后的完整代码
import React, { useState } from 'react'; import { Collapse, Button } from 'reactstrap'; import './tabs.scss'; const Tabs = () => { // 用activeIndex记录当前展开的手风琴索引,初始为null表示全部关闭 const [activeIndex, setActiveIndex] = useState(null); // 切换手风琴的函数:点击的索引和当前活跃索引一致就关闭,否则展开该项 const toggleAccordion = (index) => { setActiveIndex(prevIndex => prevIndex === index ? null : index); }; const tabObject2 = [ { tab1: 'tab1 Content' }, { tab2: 'tab2 Content' }, { tab3: 'tab3 Content' } ]; return ( <div className="tabBlock"> <div className="tab"> {tabObject2.map((ds, indexNo) => { // 获取当前项的标题和内容 const [tabTitle] = Object.keys(ds); const [tabContent] = Object.values(ds); return ( <div key={indexNo}> <Button block className="tab-btn-main" onClick={() => toggleAccordion(indexNo)} > {tabTitle} </Button> {/* 只有当activeIndex等于当前索引时,才展开内容 */} <Collapse isOpen={activeIndex === indexNo}> <div>{tabContent}</div> </Collapse> </div> ); })} </div> </div> ); }; export default Tabs;
关键改动说明
- 移除了useRef:不需要用ref来获取ID了,直接用循环的索引来区分每个手风琴项,更简单直接。
- 替换状态为activeIndex:用
activeIndex存储当前展开的项的索引,初始为null表示全部关闭;点击时判断如果是当前展开的项,就设为null关闭,否则设为对应索引展开。 - 修正事件参数传递:
onClick={() => toggleAccordion(indexNo)}确保传递的是正确的索引,而不是事件对象。 - 优化了数据提取:把
Object.keys和Object.values的结果提前解构,让代码更清晰。
这样修改后,点击任意手风琴按钮,只会展开对应的内容,其他项保持关闭,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Roy
相关产品推荐
相关产品推荐

