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
相关产品推荐
相关产品推荐

