使用react-bootstrap Accordion实现表格行展开时的DOM嵌套警告求助
解决React Bootstrap Accordion表格行展开的DOM嵌套警告
方案一:重构Accordion结构适配表格规范
核心是调整Accordion组件的渲染层级,让它生成的DOM不再嵌套在<tr>内部,完全符合HTML表格的结构要求。
修改后的代码示例:
<div className="row me-2 ms-2"> <table className="table accordian-table table header-fixed border mt-2"> <thead> <tr> <th width="30%" className="text-center">Col 1</th> <th width="30%" className="text-center">Col 2</th> <th width="30%" className="text-center">Col 3</th> <th width="25px" className="float end"></th> </tr> </thead> <tbody className="scroll"> <Accordion activeKey={activeAccordionKey} onSelect={(selectedKey) => setActiveAccordionKey(selectedKey)} flush> {items?.length ? ( [...items].map((item, index) => ( <Accordion.Item key={index} eventKey={index}> {/* 主数据行:将Accordion.Header渲染为tr */} <Accordion.Header as="tr" onClick={() => getFlows(item)} className="main-table-content"> <td width="30%" title={item.prop1} className="text-center pt-2"> {item.prop1} </td> <td width="30%" title={item.prop2} className="text-center pt-2"> {item.onboardingInfo.prop2} </td> <td width="30%" title={item.prop3} className="text-center pt-2"> {item.onboardingInfo.prop3} </td> <td width="25px">{" "}</td> </Accordion.Header> {/* 展开内容行:将Accordion.Body渲染为tr,内部td跨所有列 */} <Accordion.Body as="tr"> <td colSpan="4" onClick={(e) => e.stopPropagation()}> <table className="table"> <thead> <tr> <th>Flow Name</th> <th>Flow Type</th> <th>Dnid</th> <th>Ext</th> <th>Created By</th> <th>Created On</th> </tr> </thead> <tbody> {selectedItem?.length ? ( [...selectedItem.values()].map((slItem) => ( <tr key={slItem.flowName}> <td>{slItem.flowName}</td> <td>{slItem.flowTypeId}</td> <td>{slItem.dnid}</td> <td>{slItem.createdBy}</td> <td>{slItem.createdOn}</td> </tr> )) ) : ( <tr> <td>No Configs Available</td> </tr> )} </tbody> </table> </td> </Accordion.Body> </Accordion.Item> )) ) : ( <tr> <td colSpan="4">No ItemsFound</td> </tr> )} </Accordion> </tbody> </table> </div>
关键修改点:
- 将
<Accordion.Item>直接作为<tbody>的子元素,不再嵌套在<tr>内部 - 通过
as="tr"属性,让<Accordion.Header>和<Accordion.Body>渲染为表格行元素,而非默认的<div> - 展开内容使用
colSpan="4"的<td>包裹子表格,保证表格结构合法
方案二:手动实现展开逻辑(完全自定义DOM)
如果不想依赖Accordion组件的默认渲染,可以直接通过state控制展开状态,完全自定义符合规范的表格DOM:
<div className="row me-2 ms-2"> <table className="table accordian-table table header-fixed border mt-2"> <thead> <tr> <th width="30%" className="text-center">Col 1</th> <th width="30%" className="text-center">Col 2</th> <th width="30%" className="text-center">Col 3</th> <th width="25px" className="float end"></th> </tr> </thead> <tbody className="scroll"> {items?.length ? ( [...items].flatMap((item, index) => { const isExpanded = activeAccordionKey === index; return [ // 主数据行 <tr key={`main-${index}`} onClick={() => { getFlows(item); setActiveAccordionKey(isExpanded ? null : index); }} className="main-table-content" > <td width="30%" title={item.prop1} className="text-center pt-2"> {item.prop1} </td> <td width="30%" title={item.prop2} className="text-center pt-2"> {item.onboardingInfo.prop2} </td> <td width="30%" title={item.prop3} className="text-center pt-2"> {item.onboardingInfo.prop3} </td> <td width="25px">{" "}</td> </tr>, // 展开内容行:根据状态显示/隐藏 isExpanded && ( <tr key={`expand-${index}`}> <td colSpan="4" onClick={(e) => e.stopPropagation()}> <table className="table"> <thead> <tr> <th>Flow Name</th> <th>Flow Type</th> <th>Dnid</th> <th>Ext</th> <th>Created By</th> <th>Created On</th> </tr> </thead> <tbody> {selectedItem?.length ? ( [...selectedItem.values()].map((slItem) => ( <tr key={slItem.flowName}> <td>{slItem.flowName}</td> <td>{slItem.flowTypeId}</td> <td>{slItem.dnid}</td> <td>{slItem.createdBy}</td> <td>{slItem.createdOn}</td> </tr> )) ) : ( <tr> <td>No Configs Available</td> </tr> )} </tbody> </table> </td> </tr> ) ].filter(Boolean); }) ) : ( <tr> <td colSpan="4">No ItemsFound</td> </tr> )} </tbody> </table> </div>
这个方案完全脱离Accordion组件的约束,通过activeAccordionKey直接控制展开行的显示,DOM结构完全符合HTML表格规范,不会出现任何嵌套警告。
警告原因说明
HTML规范明确规定,<tr>的直接子元素只能是<td>、<th>等表格相关元素,而React Bootstrap的Accordion组件默认会渲染<div>元素,将其嵌套在<tr>内部就违反了DOM嵌套规则,从而触发控制台警告。上面两个方案都从结构上规避了这个问题,同时保留了原有的行展开功能。
内容的提问来源于stack exchange,提问作者Shaan Srivastava
相关产品推荐
相关产品推荐

