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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:01:23