React-Bootstrap+Next.js列表项唯一key报错问题求助
React-Bootstrap + Next.js 导航组件Key报错修复方案
问题场景
用React-Bootstrap结合Next.js开发导航组件时,触发「每个列表项需设置唯一key」的报错。已为子组件指定key,但仅下拉菜单(NavDropdown)会引发该错误,移除下拉组件后报错消失。
问题排查
仔细分析代码后,定位到几个核心问题:
filteredSubNavItems.map返回的直接子元素是<>空Fragment,未设置key。React要求map循环的直接子节点必须有唯一key,你给内部的Nav.Link/NavDropdown加了key,但外层Fragment才是map的直接子元素,这个缺失在渲染结构更复杂的NavDropdown时会被React的diff算法检测到,触发报错。- useEffect未设置依赖数组,导致组件每次渲染都执行filter逻辑,引发无限渲染,间接加重key相关的报错。
href="{navItem.link}"写法错误,双引号嵌套会把字符串原样输出,无法正确解析变量。- 部分子链接数据无
key字段,但用item.label作为key是可行的,只要label保证唯一即可。
修复后的组件代码
export default function SecondaryNav(props: NavItems) { const router = useRouter(); const [filteredSubNavItems, setFilteredSubNavItems] = useState<{}[]>([]) useEffect(() => { // 用find替代filter,找到匹配项即停止遍历,更高效 const matchedItem = props.navigation.find(item => item.link === router.route); if (matchedItem) { setFilteredSubNavItems(matchedItem.subLinks); } }, [router.route, props.navigation]); // 添加依赖数组,避免无限渲染 return ( <Navbar className={[styles.SecondaryNav].join(' ')}> <div className={['container', styles.secondaryNavContainer].join(' ')}> {filteredSubNavItems.map((navItem) => ( // 给Fragment添加唯一key,作为map的直接子元素标识 <React.Fragment key={navItem.name}> {!navItem.subLinksExist ? ( <Nav.Link key={navItem.name} href={navItem.link}>{navItem.name}</Nav.Link> ) : ( <NavDropdown key={navItem.name} title={navItem.name} id={navItem.name}> {navItem.sublinks.map((item) => ( // 补充href属性,修复下拉项无法跳转的问题 <NavDropdown.Item key={item.label} href={item.link}>{item.label}</NavDropdown.Item> ))} </NavDropdown> )} </React.Fragment> ))} </div> </Navbar> ) }
修复说明
- 给map返回的
React.Fragment添加key={navItem.name},确保map循环的直接子元素拥有唯一标识,解决核心报错问题。 - 将
filter改为find提升性能,同时给useEffect添加依赖数组[router.route, props.navigation],仅在路由或导航数据变化时执行逻辑,避免无限渲染。 - 修正
href、title的变量解析写法,去掉多余的双引号嵌套。 - 给
NavDropdown.Item补充href={item.link},修复下拉项无法跳转的问题。
内容的提问来源于stack exchange,提问作者Micah Johnson
相关产品推荐
相关产品推荐

