You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 18:01:06