React-Router-DOM v6共享布局侧边菜单无法展开问题求助
解决React Router结合复用菜单时Accordion无法展开的问题
问题根源
- SideNavEx组件参数定义错误:React组件的
children属于props对象的一部分,不能作为第二个独立参数接收,当前写法导致children无法正确传递到Accordion组件,同时可能干扰状态切换逻辑。 - HTML结构不符合规范:
GeneralMenuItems中用Link包裹li,违反了<ul>的直接子元素必须是<li>的HTML规范,可能引发潜在渲染异常。
修复方案
1. 修正SideNavEx组件参数结构
将children从props中正确解构,同时给按钮添加type="button"避免默认行为干扰:
// TestMenu.tsx import Accordion from "./TestMenuAccordion"; import { Link } from "react-router-dom"; export function SideNavEx({ label, children }: { label: string; children: React.ReactNode }) { return ( <Accordion controllerElement={(isExpanded: boolean) => ( <button type="button" className={isExpanded ? "selected" : "not-selected"}> {label} {isExpanded ? "-" : "+"} </button> )} contentDescription="menu items" > <ul className="sideNav">{children}</ul> </Accordion> ); }
2. 调整GeneralMenuItems的HTML结构
让<li>包裹<Link>,符合HTML规范:
// TestMenu.tsx 续 export function GeneralMenuItems({ url, text }: { url: string; text: string }) { return ( <li> <Link to={url}>{text}</Link> </li> ); }
3. (可选)给Accordion添加类型定义(优化代码健壮性)
替换any类型为明确的Props定义,避免类型模糊:
// TestMenuAccordion.tsx import { useState } from "react"; type AccordionProps = { controllerElement: (isExpanded: boolean) => React.ReactNode; contentDescription: string; children: React.ReactNode; }; const Accordion = ({ controllerElement, contentDescription, children, }: AccordionProps) => { const [isExpanded, setIsExpanded] = useState(false); return ( <div className="w-full mt-4"> <div aria-expanded={isExpanded} aria-controls={contentDescription} aria-label={`${isExpanded ? "隐藏" : "显示"} ${contentDescription}`} onClick={() => setIsExpanded(prev => !prev)} > {controllerElement(isExpanded)} </div> {isExpanded && ( <div id={contentDescription} className="w-full"> {children} </div> )} </div> ); }; export default Accordion;
修复效果
- 修正参数结构后,Accordion的状态切换逻辑正常触发,点击按钮可正常展开/收起菜单。
- 规范HTML结构后,消除了潜在的DOM渲染问题,同时保证了页面语义化。
- 添加
type="button"避免了按钮在特殊场景下的默认行为干扰。
内容的提问来源于stack exchange,提问作者aries0152
相关产品推荐
相关产品推荐

