NextJS 14路由匹配MDX文件报错及代码位置疑问
问题解决指南:NextJS 14 路由匹配MDX文件及常见错误修复
错误原因解析
你遇到的Error: Objects are not valid as a React child错误,本质是直接在JSX中渲染了JavaScript对象。比如你可能返回了Gray Matter解析后的完整结果(包含data和content的对象),而没有提取出可渲染的字符串或MDX内容;或者在React期望文本/元素的位置传入了对象类型的值。
路由与代码放置方案(NextJS 14 App Router)
在NextJS 14的App Router模式下,推荐用**动态路由[slug]**来匹配MDX文件名,以下是标准实现步骤:
1. 项目结构调整
你的项目根目录/ ├── app/ │ ├── [slug]/ │ │ ├── page.jsx # 动态路由页面组件 ├── mdx-pages/ │ ├── test.mdx │ ├── focus.mdx │ ├── space.mdx
2. 编写MDX文件读取工具函数
新建utils/mdxUtils.js封装文件读取和解析逻辑:
import fs from 'fs'; import path from 'path'; import matter from 'gray-matter'; import { compileMDX } from 'next-mdx-remote/rsc'; // MDX文件存放路径 const MDX_FILE_DIR = path.join(process.cwd(), 'mdx-pages'); export async function getMdxContent(slug) { const targetPath = path.join(MDX_FILE_DIR, `${slug}.mdx`); // 先检查文件是否存在 if (!fs.existsSync(targetPath)) { return null; } // 读取文件并解析Frontmatter const rawContent = fs.readFileSync(targetPath, 'utf8'); const { data: frontmatter, content: rawMdx } = matter(rawContent); // 编译MDX内容(适配App Router服务器组件) const { content: compiledMdx } = await compileMDX({ source: rawMdx, options: { parseFrontmatter: true }, }); return { frontmatter, content: compiledMdx }; }
3. 动态路由页面实现(app/[slug]/page.jsx)
import { notFound } from 'next/navigation'; import { getMdxContent } from '@/utils/mdxUtils'; // 预生成所有存在的MDX页面路由(静态优化) export async function generateStaticParams() { const fs = require('fs'); const path = require('path'); const fileNames = fs.readdirSync(path.join(process.cwd(), 'mdx-pages')); return fileNames.map(fileName => ({ slug: fileName.replace('.mdx', ''), })); } export default async function MdxPage({ params }) { const { slug } = params; const pageData = await getMdxContent(slug); // 文件不存在时返回404 if (!pageData) { notFound(); } // 重点:只渲染可解析的内容,不要直接渲染pageData对象 return ( <div className="container mx-auto py-8"> <h1 className="text-3xl font-bold mb-4">{pageData.frontmatter.title || slug}</h1> {/* 渲染编译后的MDX内容 */} {pageData.content} </div> ); }
4. 错误修复关键点
- 绝对不要直接渲染
pageData这类对象,必须提取其中的content(编译后的MDX)或frontmatter中的具体字段(如title、description等字符串类型值)。 - 确认使用
compileMDX编译原始MDX内容,返回的content是可直接渲染的React元素,而非原始字符串或未解析对象。
next.config.js 配置参考
确保你的NextJS配置正确支持MDX:
/** @type {import('next').NextConfig} */ const nextConfig = { pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'], // 其他自定义配置... }; const withMDX = require('@next/mdx')(); module.exports = withMDX(nextConfig);
额外注意事项
- App Router中,文件系统读取必须在服务器组件中完成(页面组件默认是服务器组件),禁止在客户端组件中执行文件IO操作。
- 使用
generateStaticParams可以预渲染所有MDX页面,提升访问速度。 - 务必添加文件存在性检查,避免抛出文件未找到的异常,用
notFound()统一返回404页面。
内容的提问来源于stack exchange,提问作者Owaiz Yusufi
相关产品推荐
相关产品推荐

