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

Next.js13 App目录下MDXRemote触发无效Hook调用错误求助

解决Next.js 13 App目录中next-mdx-remote的钩子调用错误

错误根源

你碰到的Invalid hook call和Cannot read properties of null (reading 'useState')错误,核心原因是Next.js 13 App目录的组件模型限制:

  • App目录下的组件默认是服务器组件,这类组件不能使用React钩子(比如useState)。
  • MDXRemote内部依赖钩子处理MDX内容渲染,你直接在服务器组件里使用它,还加了ssr: false的动态导入,导致组件在服务端上下文错误触发钩子调用,最终抛出异常。

解决方案

1. 拆分客户端组件专门处理MDX渲染

新建一个带'use client'指令的客户端组件,专门负责渲染MDXRemote:

// src/components/PostContent.tsx
'use client';

import { MDXRemote } from 'next-mdx-remote';
import MDXComponents from './mdx-components';

type Props = {
  mdxSource: Awaited<ReturnType<typeof import('@/lib/mdx').getPost>>['mdxSource'];
};

export default function PostContent({ mdxSource }: Props) {
  return <MDXRemote {...mdxSource} components={MDXComponents} />;
}

2. 修改页面服务器组件

保持页面组件为服务器组件,负责获取MDX数据,再传给上面的客户端组件渲染:

// src/app/blog/post/post1/page.tsx
import { getPost } from '@/lib/mdx';
import PostContent from '@/components/PostContent';

export default async function BlogPost() {
  const slug = 'post1';
  const { mdxSource, frontMatter } = await getPost(slug);

  if (!mdxSource) {
    return <div>404 - maaz here</div>;
  }

  return (
    <div>
      <h1>{frontMatter.title}</h1>
      <PostContent mdxSource={mdxSource} />
    </div>
  );
}

3. 清理多余配置

删掉之前用dynamic导入MDXRemote的代码,'use client'指令已经明确标记了客户端组件,符合App目录的渲染规范,不需要再用ssr: false强制客户端渲染。

额外提醒

  • getPost函数依赖fs.readFileSync,只能在服务器组件中调用,不能放到客户端组件里。
  • 如果你的MDXComponents里有使用钩子的自定义组件,也要给这些组件加上'use client'指令。

内容的提问来源于stack exchange,提问作者Maaz Mustafa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 23:43:09