React中使用Rsuite实现4级导航菜单报错求助
问题:Rsuite导航菜单无法实现4级子菜单
问题描述
- 使用Rsuite构建导航菜单,需求是支持4级子菜单,但目前仅能实现「主菜单+1级子菜单」的结构
- 注释的代码尝试实现多级菜单,但运行时报错:第31行无法对unknown执行map操作
- 未注释的代码仅支持1级子菜单,可正常运行
报错信息
第31行无法对unknown执行map操作
原代码
import {NavLink} from 'react-router-dom'; import {Navbar, Nav} from 'rsuite'; export default function Header(){ let menu = [ {name: 'Varejos de Cão', key: 13, subitems: [ // e {name: 'Golden', key: 1, subitems: [ // sub {name: 'Raças Pequenas', key: 2, subitems: [ // nvl2 // {name: 'Adulto Carne', key: 3, link: '/golden_cao_ad_rpq_carne'}, // nvl3 // {name: 'Adulto Frango', key: 4, link: '/golden_cao_ad_rpq_frango'}, // {name: 'Filhote Carne', key: 5, link: '/golden_cao_fil_rpq_carne'}, ]} ]} ]}, {name: 'Varejos de Gato', key: 14, subitems: [ {name: 'Golden', key: 3, link: '#'} ]}, {name: 'Nossas Lojas', key: 15, subitems: [ {name: 'Tanque', key: 6, link: '/tanque'}, {name: 'Vila Isabel', key: 7, link: '/vila'}, {name: 'Grajau', key: 8, link: '/grajau'}, {name: 'Pechincha', key: 9, link: '/pechincha'}, {name: 'Catete', key: 10, link: '/catete'}, {name: 'Jacarepagua', key: 12, link: '/jacarepagua'}, {name: 'Tijuca', key: 11, link: '/tijuca'} ]} ]; // let menu_options = menu.map((e, k) => { // let subs = e.subitems.map((nvl1, sub_k) => { // let nvs2 = nvl1.subitems.map((nvl2, sub_k) => { // return( // <Nav.Item className="navigation-item" key={nvl2.key} eventKey={nvl2.key}><NavLink className="header-link" to={nvl2.link}>{nvl2.name}</NavLink></Nav.Item> // ); // }); // return( // <Nav.Menu title={nvl1.name} key={nvl1.key}> // {nvs2} // </Nav.Menu> // ); // }); // return( // <Nav.Menu title={e.name} key={k}> // {subs} // </Nav.Menu> // ); // }); let menu_options = menu.map((e, k) => { let subs = e.subitems.map((sub, sub_k) => { return( <Nav.Item className="navigation-item" key={sub.key} eventKey={sub.key}><NavLink className="header-link" to={sub.link}>{sub.name}</NavLink></Nav.Item> ); }); return( <Nav.Menu title={e.name} key={e.key}> {subs} </Nav.Menu> ); }); return( <div id="page-header"> <nav id="menu-desktop"> <div id="header-menu"> <Navbar> <Navbar.Brand href="#">Dogão Pet Shop Varejos</Navbar.Brand> <Nav className="header-navigation"> {/* <Nav.Item eventKey="1" href="/home">Home</Nav.Item> */} {menu_options} </Nav> </Navbar> </div> </nav> {/* <nav id="menu-mobile"> <div id="header-menu"> <Navbar> <Nav className="header-navigation"> <Nav.Menu title="Menu"> <Nav.Item className="navigation-item" eventKey="1"><NavLink className="header-link" to="/home">Home</NavLink></Nav.Item> {menu_options} </Nav.Menu> </Nav> </Navbar> </div> </nav> */} </div> ) }
问题原因
- 缺少空值判断:部分菜单项(比如
Varejos de Gato下的Golden)没有subitems属性,代码直接调用nvl1.subitems.map时,nvl1.subitems为undefined,导致报错 - 硬编码层级限制:注释代码仅写了3层嵌套逻辑,无法支持4级子菜单,且没有区分「带链接的叶子节点」和「带子菜单的父节点」
修复方案:递归渲染多级菜单
通过递归函数自动处理任意层级的子菜单,同时增加空值判断避免报错:
import { NavLink } from 'react-router-dom'; import { Navbar, Nav } from 'rsuite'; export default function Header() { let menu = [ {name: 'Varejos de Cão', key: 13, subitems: [ {name: 'Golden', key: 1, subitems: [ {name: 'Raças Pequenas', key: 2, subitems: [ {name: 'Adulto Carne', key: 3, link: '/golden_cao_ad_rpq_carne'}, {name: 'Adulto Frango', key: 4, link: '/golden_cao_ad_rpq_frango'}, {name: 'Filhote Carne', key: 5, link: '/golden_cao_fil_rpq_carne'}, ]} ]} ]}, {name: 'Varejos de Gato', key: 14, subitems: [ {name: 'Golden', key: 3, link: '#'} ]}, {name: 'Nossas Lojas', key: 15, subitems: [ {name: 'Tanque', key: 6, link: '/tanque'}, {name: 'Vila Isabel', key: 7, link: '/vila'}, {name: 'Grajau', key: 8, link: '/grajau'}, {name: 'Pechincha', key: 9, link: '/pechincha'}, {name: 'Catete', key: 10, link: '/catete'}, {name: 'Jacarepagua', key: 12, link: '/jacarepagua'}, {name: 'Tijuca', key: 11, link: '/tijuca'} ]} ]; // 递归渲染菜单项,自动识别层级 const renderMenuItem = (item) => { // 有子菜单时渲染为Nav.Menu if (item.subitems && item.subitems.length > 0) { return ( <Nav.Menu title={item.name} key={item.key}> {item.subitems.map(subItem => renderMenuItem(subItem))} </Nav.Menu> ); } // 没有子菜单时渲染为Nav.Item(叶子节点) return ( <Nav.Item className="navigation-item" key={item.key} eventKey={item.key}> <NavLink className="header-link" to={item.link || '#'}>{item.name}</NavLink> </Nav.Item> ); }; const menu_options = menu.map(item => renderMenuItem(item)); return ( <div id="page-header"> <nav id="menu-desktop"> <div id="header-menu"> <Navbar> <Navbar.Brand href="#">Dogão Pet Shop Varejos</Navbar.Brand> <Nav className="header-navigation"> {menu_options} </Nav> </Navbar> </div> </nav> {/* <nav id="menu-mobile"> <div id="header-menu"> <Navbar> <Nav className="header-navigation"> <Nav.Menu title="Menu"> <Nav.Item className="navigation-item" eventKey="1"><NavLink className="header-link" to="/home">Home</NavLink></Nav.Item> {menu_options} </Nav.Menu> </Nav> </Navbar> </div> </nav> */} </div> ) }
关键改进点
- 递归逻辑:自动适配任意层级的子菜单,无需修改代码即可支持4级甚至更多级
- 安全判断:每次调用
map前检查subitems是否存在且不为空,避免undefined报错 - 节点区分:自动识别叶子节点(带链接)和父节点(带子菜单),渲染对应组件
内容的提问来源于stack exchange,提问作者Diogo Amaral
相关产品推荐
相关产品推荐

