Next.js组件出现TypeError: Cannot read properties of undefined (reading 'map')问题
问题描述
原本在index.js和/blog/index.js中成功实现了包含map方法的博客列表功能,将这部分可复用代码抽离为BlogPosts2.jsx组件后,运行时抛出TypeError: Cannot read properties of undefined (reading 'map')错误。尝试使用posts?.map处理后,页面仅显示空白,无法正常渲染博客内容。
原页面代码
import fs from "fs" import * as path from "path" import matter from "gray-matter" import Link from "next/link" import Image from "next/image" export default function Home( { posts } ) { return ( <div className="mt-5"> <div className="font-semibold text-2xl flex flex-auto justify-center"> <div className="bg-orange-400 p-5 rounded-3xl">All Posts:</div></div> {posts.map((post, index) => ( <Link href={'/blog/' + post.slug} passHref key={index}> <div className="mt-3 cursor-pointer text-center"> <div className="m-2"> <h1 className="text-center">{post.frontMatter.title}</h1> <p className="mt-3 text-center">{post.frontMatter.description}</p> <p className="mt-3 text-center">{post.frontMatter.date}</p> </div> <div className="p-5"> <Image className="rounded-3xl" src={post.frontMatter.thumbnailUrl} alt={post.frontMatter.title} width={500} height={500} /> </div> </div> </Link> ))} </div> ) } export const getStaticProps = async () => { const files = fs.readdirSync(path.join('src', 'posts')) const posts = files.map(filename => { const markdownWithMeta = fs.readFileSync(path.join('src', 'posts', filename)) const { data:frontMatter } = matter(markdownWithMeta) return { frontMatter, slug: filename.split('.')[0] } }) return { props: { posts } } }
BlogPosts2.jsx组件代码
import fs from "fs" import * as path from "path" import matter from "gray-matter" import Link from "next/link" import Image from "next/image" const BlogPosts2 = ( {posts} ) => { return ( <div className="mt-5"> <div className="font-semibold text-2xl flex flex-auto justify-center"> <div className="bg-orange-400 p-5 rounded-3xl">All Posts:</div> </div> {posts.map((post, index) => ( <Link href={'/blog/' + post.slug} passHref key={index}> <div className="mt-3 cursor-pointer text-ce1nter"> <div className="m-2"> <h1 className="text-center">{post.frontMatter.title}</h1> <p className="mt-3 text-center">{post.frontMatter.description}</p> <p className="mt-3 text-center">{post.frontMatter.date}</p> </div> <div className="p-5"> <Image className="rounded-3xl" src={post.frontMatter.thumbnailUrl} alt={post.frontMatter.title} width={500} height={500} /> </div> </div> </Link> ))} </div> ) } export const getStaticProps = async () => { const files = fs.readdirSync(path.join('src', 'posts')) const posts = files.map(filename => { const markdownWithMeta = fs.readFileSync(path.join('src', 'posts', filename)) const { data:frontMatter } = matter(markdownWithMeta) return { frontMatter, slug: filename.split('.')[0] } }) return { props: { posts } } } export default BlogPosts2
解决方案
核心问题
Next.js中getStaticProps仅在pages目录下的页面组件中生效,抽离的普通组件无法直接通过该方法获取数据,导致posts参数始终为undefined,触发map报错;使用posts?.map后,因posts为undefined跳过了渲染逻辑,所以页面空白。
修复步骤
1. 修改BlogPosts2组件,移除无效的getStaticProps
import Link from "next/link"; import Image from "next/image"; const BlogPosts2 = ({ posts }) => { // 给posts设置默认空数组,避免undefined导致的问题 const safePosts = posts || []; return ( <div className="mt-5"> <div className="font-semibold text-2xl flex flex-auto justify-center"> <div className="bg-orange-400 p-5 rounded-3xl">All Posts:</div> </div> {/* 无数据时显示提示 */} {safePosts.length === 0 ? ( <p className="text-center mt-5">暂无博客文章</p> ) : ( safePosts.map((post, index) => ( <Link href={`/blog/${post.slug}`} passHref key={index}> <div className="mt-3 cursor-pointer text-center"> <div className="m-2"> <h1 className="text-center">{post.frontMatter.title}</h1> <p className="mt-3 text-center">{post.frontMatter.description}</p> <p className="mt-3 text-center">{post.frontMatter.date}</p> </div> <div className="p-5"> <Image className="rounded-3xl" src={post.frontMatter.thumbnailUrl} alt={post.frontMatter.title} width={500} height={500} /> </div> </div> </Link> )) )} </div> ); }; export default BlogPosts2;
2. 在页面组件中引入并传递posts数据
以index.js为例,保留原有的getStaticProps逻辑,将获取到的posts通过props传给组件:
import fs from "fs"; import * as path from "path"; import matter from "gray-matter"; import BlogPosts2 from "../components/BlogPosts2"; // 注意组件实际路径 export default function Home({ posts }) { return <BlogPosts2 posts={posts} />; } export const getStaticProps = async () => { const files = fs.readdirSync(path.join('src', 'posts')); const posts = files.map(filename => { const markdownWithMeta = fs.readFileSync(path.join('src', 'posts', filename)); const { data: frontMatter } = matter(markdownWithMeta); return { frontMatter, slug: filename.split('.')[0] }; }); return { props: { posts } }; };
额外修正
组件中存在拼写错误:text-ce1nter改为text-center,避免样式异常。
内容的提问来源于stack exchange,提问作者Klim Yadrintsev
相关产品推荐
相关产品推荐

