Next.js中[slug].jsx页面Sidebar组件map读取undefined错误排查
问题根源
Next.js 中getStaticProps仅能在页面组件(即pages目录下的[slug].jsx、index.jsx这类文件)中生效,你将其写在SideBar这种普通组件里时,数据获取逻辑不会被执行,导致articles参数未被传递,最终调用map时触发“读取undefined属性”的错误。
解决方案
方案1:将数据获取移至页面组件[slug].jsx
在页面组件的getStaticProps中同时获取当前文章与侧边栏推荐内容,再将推荐列表传递给SideBar组件:
// [slug].jsx import { createClient } from 'contentful'; import SideBar from './SideBar'; export async function getStaticProps(context) { const client = createClient({ space: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_KEY, }); // 获取当前文章 const articleRes = await client.getEntry(context.params.slug); // 获取侧边栏推荐文章(直接限制返回5条) const sidebarRes = await client.getEntries({ content_type: "news", limit: 5 }); return { props: { currentArticle: articleRes, sidebarArticles: sidebarRes.items, }, revalidate: 1 }; } export default function ArticlePage({ currentArticle, sidebarArticles }) { return ( <div className="container"> {/* 当前文章内容区域 */} <div className="article-content">...</div> {/* 传递推荐列表给SideBar */} <SideBar articles={sidebarArticles} /> </div> ); }
修改SideBar组件,移除无效的getStaticProps,并给articles设置默认空数组避免报错:
// SideBar.jsx import SideBarCard from './Cards/SideBarCard' export default function SideBar({ articles = [] }) { return ( <div className=""> <div className="sideCard mb-2"> إعلان </div> <div className="sideBar mb-2"> <h2 className="text-white w-fit text-3xl mb-4 font-massir rounded-2xl border-light border p-2">أقرا المزيد</h2> <div className="sticky top-0 space-y-4"> {articles.map((news) => ( <SideBarCard key={news.sys.id} news={news} /> ))} </div> </div> </div> ) }
方案2:在SideBar组件内部直接获取数据
若使用Next.js 13+ App Router(服务器组件)
将SideBar设为服务器组件,直接在组件内异步获取数据:
// SideBar.jsx import { createClient } from 'contentful'; import SideBarCard from './Cards/SideBarCard' const client = createClient({ space: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_KEY, }); export default async function SideBar() { const res = await client.getEntries({ content_type: "news", limit: 5 }); const articles = res.items || []; return ( <div className=""> <div className="sideCard mb-2"> إعلان </div> <div className="sideBar mb-2"> <h2 className="text-white w-fit text-3xl mb-4 font-massir rounded-2xl border-light border p-2">أقرا المزيد</h2> <div className="sticky top-0 space-y-4"> {articles.map((news) => ( <SideBarCard key={news.sys.id} news={news} /> ))} </div> </div> </div> ) }
若使用Pages Router(客户端组件)
通过useEffect在客户端触发数据获取:
// SideBar.jsx import { useState, useEffect } from 'react'; import { createClient } from 'contentful'; import SideBarCard from './Cards/SideBarCard' export default function SideBar() { const [articles, setArticles] = useState([]); useEffect(() => { const fetchArticles = async () => { const client = createClient({ space: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_KEY, }); const res = await client.getEntries({ content_type: "news", limit: 5 }); setArticles(res.items || []); }; fetchArticles(); }, []); return ( <div className=""> <div className="sideCard mb-2"> إعلان </div> <div className="sideBar mb-2"> <h2 className="text-white w-fit text-3xl mb-4 font-massir rounded-2xl border-light border p-2">أقرا المزيد</h2> <div className="sticky top-0 space-y-4"> {articles.map((news) => ( <SideBarCard key={news.sys.id} news={news} /> ))} </div> </div> </div> ) }
额外提示
- 始终给
articles设置默认空数组,即使数据获取失败也不会导致页面崩溃。 - 在Contentful请求中通过
limit参数限制返回数量,避免前端再做索引判断,提升性能。
内容的提问来源于stack exchange,提问作者Eyad Farah
相关产品推荐
相关产品推荐

