React中嵌套map渲染菜单并过滤重复项的实现问题咨询
问题核心原因
你现在的写法存在3个共性错误,导致无法正常渲染:
- 没有显式返回JSX元素:map回调中编写的
<Typography>组件没有加return,React无法识别这些元素 - 缺少父容器包裹:React不允许同一个回调返回多个无父节点的同级元素,需要用Fragment或容器组件包裹
- 匹配逻辑不合理:直接在map中做if判断会生成大量undefined空项,同时每次嵌套都遍历全量子数组,容易出现重复匹配、逻辑混乱的问题
实现方案
推荐先把接口返回的扁平数据转成嵌套结构,再做渲染,逻辑更清晰,后续维护也更方便:
步骤1:结构化处理数据
const nestedMenu = LocationMenuStore.menuItems.menu.headings.map(heading => { // 匹配当前一级标题对应的所有二级标题 const relatedSubHeadings = LocationMenuStore.menuItems.menu.sub_headings .filter(sub => sub.menu_heading_id === heading.id) .map(subHeading => { // 匹配当前二级标题对应的所有菜单项 const relatedItems = LocationMenuStore.menuItems.menu.items.filter( item => item.sub_heading_id === subHeading.id ) return { ...subHeading, items: relatedItems } }) return { ...heading, subHeadings: relatedSubHeadings } })
步骤2:嵌套渲染菜单
const fullMenu = nestedMenu.map(heading => ( <React.Fragment key={heading.id}> {/* 一级标题 */} <Typography>{heading.heading_name}</Typography> {/* 渲染二级标题 */} {heading.subHeadings.map(subHeading => ( <React.Fragment key={subHeading.id}> <Typography style={{ paddingLeft: '16px' }}>{subHeading.sub_heading_name}</Typography> {/* 渲染菜单项 */} {subHeading.items.map(item => ( <Typography key={item.id} style={{ paddingLeft: '32px' }}>{item.item_name}</Typography> ))} </React.Fragment> ))} </React.Fragment> ))
如果不想提前处理数据,也可以直接在渲染时做filter+map,效果一致:
const fullMenu = LocationMenuStore.menuItems.menu.headings.map(heading => ( <React.Fragment key={heading.id}> <Typography>{heading.heading_name}</Typography> {LocationMenuStore.menuItems.menu.sub_headings .filter(sub => sub.menu_heading_id === heading.id) .map(subHeading => ( <React.Fragment key={subHeading.id}> <Typography style={{ paddingLeft: '16px' }}>{subHeading.sub_heading_name}</Typography> {LocationMenuStore.menuItems.menu.items .filter(item => item.sub_heading_id === subHeading.id) .map(item => ( <Typography key={item.id} style={{ paddingLeft: '32px' }}>{item.item_name}</Typography> )) } </React.Fragment> )) } </React.Fragment> ))
代码中的paddingLeft仅为了体现层级缩进,你可以根据实际UI需求替换为自定义类名或其他样式规则,key属性必须添加,可避免React渲染警告和重复渲染问题。
内容的提问来源于stack exchange,提问作者Shay Kitoff
相关产品推荐
相关产品推荐

