TSX环境下NextJS项目React Markdown集成SyntaxHighlighter报错如何解决?
问题根因
该报错是两处问题共同导致的:
- 类型不兼容:react-markdown 传递给
code组件的ref属性是用于绑定原生<code>DOM 元素的,但SyntaxHighlighter组件的ref预期绑定自身组件实例,二者类型冲突。你之前注释{...props}虽然绕开了类型报错,但丢失了react-markdown传递的必要属性,自然无法触发高亮。 - NextJS服务端渲染不兼容:
react-syntax-highlighter依赖浏览器端API运行,NextJS默认服务端渲染会导致组件初始化失败,即使类型问题解决也不会出现高亮效果。
解决步骤
1. 调整导入方式(NextJS专属)
不要直接导入SyntaxHighlighter,使用next/dynamic关闭服务端渲染:
import dynamic from 'next/dynamic'; // 若使用Prism版本的语法高亮 const SyntaxHighlighter = dynamic(() => import('react-syntax-highlighter').then(mod => mod.Prism), { ssr: false }); // 若使用Highlight.js版本的语法高亮,替换为下面的导入 // const SyntaxHighlighter = dynamic(() => import('react-syntax-highlighter'), { ssr: false }); import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
2. 修复类型冲突
解构code组件入参时单独提取ref,仅传给原生<code>标签,不传递给SyntaxHighlighter:
const BlogPost = ({ frontMatter, markdownBody }: BlogPostProps) => { if (!frontMatter) return <></>; return ( <Layout> <ReactMarkdown components={{ code({ node, inline, className, children, ref, ...props }) { const match = /language-(\w+)/.exec(className || ""); return !inline && match ? ( <SyntaxHighlighter style={vscDarkPlus} language={match[1]} PreTag="div" {...props} > {String(children).replace(/\n$/, "")} </SyntaxHighlighter> ) : ( <code className={className} ref={ref} {...props}> {children} </code> ); }, }} > {markdownBody} </ReactMarkdown> </Layout> ); };
可选兜底方案
如果仍有类型报错,可以给props增加临时类型断言,不影响实际运行效果:
<SyntaxHighlighter style={vscDarkPlus} language={match[1]} PreTag="div" {...props as any} >
内容的提问来源于stack exchange,提问作者hyl3rid
相关产品推荐
相关产品推荐

