# React 快速开始 在你的 React 项目中开始使用 markstream-react。 ::: tip 正在从 react-markdown 迁移? 如果你的应用已经在使用 `react-markdown`,建议先看[迁移指南](/zh/guide/react-markdown-migration)和[迁移 Cookbook](/zh/guide/react-markdown-migration-cookbook),再开始手动改代码。 ::: ## 基础设置 ### 1. 安装 首先,安装包: ```bash pnpm add markstream-react ``` ### 2. 导入样式 在你的主入口文件(如 `main.tsx`、`index.tsx` 或 `App.tsx`)中: ```tsx import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import 'markstream-react/index.css' ReactDOM.createRoot(document.getElementById('root')!).render( ) ``` ### 3. 使用组件 ```tsx import MarkdownRender from 'markstream-react' function App() { const markdown = `# Hello React! 这是 **markstream-react** - 适用于 React 的流式 Markdown 渲染器。 ## 功能 - 代码语法高亮 - Mermaid 图表 - 数学公式 - 还有更多功能! \`\`\`javascript console.log('Hello from React!') \`\`\` ` return (
) } export default App ``` ## 使用 TypeScript markstream-react 使用 TypeScript 构建,包含完整的类型定义: ```tsx import type { NodeRendererProps } from 'markstream-react' import MarkdownRender from 'markstream-react' const props: NodeRendererProps = { content: '# Hello TypeScript!', } function App() { return } ``` ## 使用 Next.js 不要再把 `mounted` guard 或 `ssr: false` 当成主接法,Next 现在有专门的 SSR 双入口。 完整说明见 [React Next SSR](/zh/guide/react-next-ssr)。 ### App Router(Next.js 14 / 15) ```tsx import MarkdownRender from 'markstream-react/next' export default function MarkdownPage() { const markdown = `# Hello Next.js! 这个路由会先返回真实 SSR HTML。 ` return } ``` ### Pages Router ```tsx import MarkdownRender from 'markstream-react/next' import 'markstream-react/index.css' export default function MarkdownPage() { const markdown = `# Hello Next.js Pages Router!` return } ``` ### 纯服务端渲染 ```tsx import MarkdownRender from 'markstream-react/server' export default function MarkdownPage() { const markdown = `# 纯 server 入口` return } ``` ## 启用可选功能 ### 代码语法高亮 安装依赖: ```bash pnpm add stream-markdown ``` ```tsx import MarkdownRender, { MarkdownCodeBlockNode, setCustomComponents } from 'markstream-react' // 在 MarkdownRender 中使用 Shiki 代码块 setCustomComponents({ code_block: ({ node, isDark, ctx }: any) => ( ), }) function App() { const markdown = `\`\`\`javascript const hello = 'world' console.log(hello) \`\`\`` return } ``` ### Mermaid 图表 安装 mermaid: ```bash pnpm add mermaid ``` 导入样式(安装后会自动加载 Mermaid): ```tsx import 'markstream-react/index.css' function App() { const markdown = `#### Mermaid 图表 \`\`\`mermaid graph TD A[开始] --> B{能用吗?} B -->|是| C[太好了!] B -->|否| D[继续尝试] \`\`\`` return } ``` ### D2 图表 安装 D2: ```bash pnpm add @terrastruct/d2 ``` ```tsx import 'markstream-react/index.css' function App() { const markdown = `#### D2 图表 \`\`\`d2 direction: right Client -> API: request API -> DB: query DB -> API: rows API -> Client: response \`\`\`` return } ``` ### 数学公式(KaTeX) 安装 katex: ```bash pnpm add katex ``` 导入样式(安装后会自动加载 KaTeX): ```tsx import 'markstream-react/index.css' import 'katex/dist/katex.min.css' function App() { const markdown = `#### 数学示例 行内数学公式:$E = mc^2$ 块级数学公式: $$ \\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2} $$` return } ``` ## 自定义组件 你可以通过传递自定义组件映射来自定义特定节点的渲染方式: ```tsx import MarkdownRender, { setCustomComponents } from 'markstream-react' // 自定义标题组件 function CustomHeading({ node, customId }: any) { const level = node.level || 1 const Tag = `h${level}` as keyof JSX.IntrinsicElements return ( {node.children?.map((child: any, i: number) => ( {child.content || ''} ))} ) } // 挂载到指定的 customId 作用域 setCustomComponents('docs', { heading: CustomHeading }) function App() { const markdown = `# 自定义标题 此标题使用自定义组件渲染。 ` return } ``` ## 流式内容 markstream-react 支持流式 markdown 内容,适用于 AI 生成的内容: ```tsx import MarkdownRender from 'markstream-react' import { useState } from 'react' function StreamingDemo() { const [markdown, setMarkdown] = useState('') const [isStreaming, setIsStreaming] = useState(false) const fullText = `# 流式传输演示 此内容正在**逐步**流式传输。 ## 功能 1. 渐进式渲染 2. 无布局偏移 3. 流畅动画 \`\`\`javascript const streaming = true console.log('流式传输已启用:', streaming) \`\`\` ` const startStreaming = () => { setIsStreaming(true) setMarkdown('') let i = 0 const interval = setInterval(() => { if (i < fullText.length) { setMarkdown(prev => prev + fullText[i]) i++ } else { clearInterval(interval) setIsStreaming(false) } }, 20) return () => clearInterval(interval) } return (
) } ``` ## 使用 React Hooks ```tsx import type { ChangeEvent } from 'react' import MarkdownRender from 'markstream-react' import { useCallback, useEffect, useState } from 'react' function MarkdownEditor() { const [content, setContent] = useState('# 编辑我!') const [html, setHtml] = useState('') const handleChange = useCallback((e: ChangeEvent) => { setContent(e.target.value) }, []) return (