Next.js获取Strapi数据控制台可见但UI无法显示问题排查
问题根因
一共三个核心问题导致菜单无法正常渲染:
- 数据适配逻辑层级错误,且触发了Chrome控制台打印引用的经典坑
接口返回结构中,data.menus.data是菜单实体列表(当前仅返回1个英文菜单实体),实际可渲染的菜单项数组存放在该实体的attributes.Entry字段下。现有适配器直接遍历传入的menuData外层数组,拿到的entry实际是整个菜单项数组,直接访问数组的link/title属性只能得到undefined。
控制台中看到的正确数组是Chrome控制台的机制导致:打印对象/数组时输出的是内存引用,手动展开控制台查看时,变量已经被后续逻辑更新为正确值,不代表组件渲染那一刻拿到的是有效数据。 - 缺少异步数据空值兜底
GraphQL请求是异步的,组件首次渲染时从Context拿到的menuData默认是undefined,直接执行menuData.map()会抛出类型错误,直接中断组件渲染流程。 - Next.js Link组件用法与版本不兼容
如果使用Next.js 13及以上版本,next/link组件本身就会渲染为<a>标签,内部再嵌套<a>标签会生成非法的<a><a>文本</a></a>嵌套结构,浏览器解析HTML时会自动修正错误结构,将内层a标签移出,最终导致菜单项文本丢失。 - 附加逻辑问题:所有Link的href都写死为
/,就算渲染成功点击也无法跳转到对应菜单页面。
修复方案
- 修正适配器逻辑,先定位到实际菜单项数组再做格式转换,同时增加空值兜底:
const mainMenuAdapter = (menuData) => { // 空值兜底,避免首次渲染时执行map报错 if (!menuData || !Array.isArray(menuData) || menuData.length === 0) { return [] } // 取出第一个菜单实体下的Entry菜单项数组 const menuEntries = menuData[0]?.attributes?.Entry || [] // 遍历菜单项做格式转换 return menuEntries.map(entry => ({ link: entry.link, title: entry.title, })) }
- 修正渲染逻辑,适配Next.js版本规范:
- Next.js 12及更早版本可保留内部a标签,但需替换href为实际菜单链接
- Next.js 13及以上版本直接移除内部嵌套的a标签,将样式类名直接添加到Link组件上
以Next.js 13+版本为例,修正后的代码如下:
<div className="bg-green-400 relative filosofia_regular bg-grayDark flex-wrap md:flex flex-row items-end md:justify-around p-2 lg:justify-evenly text-center mx-auto w-full"> {menus.map((menu, i) => { return ( <div key={menu.link || i}> <Link href={menu.link || "/"} className="text-gray-100 px-2 text-sm lg:text-2xl xl:text-4xl whitespace-nowrap" > {t(menu.title)} </Link> {i < menus.length - 1 && ( <span className="text-white">|</span> )} </div> ); })} </div>
注意:菜单分隔符
|不要使用a标签,改用span即可避免不必要的可访问性问题;key优先使用唯一标识(如menu.link),不要直接用数组索引,减少重渲染时的异常。
- 校验GlobalContext状态更新逻辑:拿到菜单数据后必须通过
useState的更新方法修改context中的menuData值,确保值变化时能触发所有订阅context的组件重渲染。
额外提示:接口返回的classes菜单项链接写为./calss.html存在拼写错误,建议同步修正为./classes.html避免跳转404。
内容的提问来源于stack exchange,提问作者Divad
相关产品推荐
相关产品推荐

