react-markdown 的 7 个常见坑与最佳实践换行、缩进与 HTML 转义一次讲清【免费下载链接】react-markdownMarkdown component for React项目地址: https://gitcode.com/gh_mirrors/re/react-markdownreact-markdown 是 React 生态里渲染 Markdown 的主流组件它把 Markdown 文本安全地解析成 React 元素而不是拼接 HTML 字符串不用dangerouslySetInnerHTML天生防 XSS。但在实际项目中换行被吞、缩进变代码块、HTML 被转义这三类问题几乎人人踩过。本文带你一次讲清 7 个最常见的坑并给出可以直接照做的最佳实践。快速上手与项目一览先安装并渲染一段 Markdownnpm install react-markdown import Markdown from react-markdown Markdown{# Hi, *Pluto*!}/Markdown // 渲染为h1Hi, emPluto/em!/h1特性说明 默认安全不走dangerouslySetInnerHTML没有 XSS 攻击面 组件可替换## 标题可以渲染成你自己的组件而不只是h2 插件生态基于 unified / remark / rehypeGFM、数学公式等都有现成插件 规范合规默认 100% 符合 CommonMark加remark-gfm后 100% 符合 GFM⚠️ 注意该包是ESM only需要 Node 16 和打包工具webpack / Vite / esbuild 等浏览器里不能直接写script引它。坑 1换行不生效——在 JSX 里直接写 Markdown 会被压扁现象把 Markdown 直接写在标签中间换行全部消失标题和正文合并成一个段落。原因JSX 本身会折叠空白多行文字会被压缩成一行。官方在 readme.md 附录 C 专门写了这个问题。❌ 错误写法等价于一行纯文本Markdown # Hi This is a paragraph. /Markdown✅ 最佳实践把 Markdown 放进变量再用表达式传入——这是react-markdown 换行不生效的万能解法const markdown # Hi This is a paragraph. Markdown{markdown}/Markdown坑 2缩进让标题变成代码块原因模板字符串会保留缩进而 CommonMark 规定4 个空格缩进 缩进代码块。于是标题悄悄变成了灰色代码框Markdown{ # 这不是标题是一个缩进代码块 }/Markdown✅ 最佳实践写在代码里的 Markdown顶格写、不要缩进。变量本身可以缩进但 Markdown 内容的每一行都不要带前导空格。坑 3HTML 被转义成纯文本——这是默认行为不是 Bug在 Markdown 里写ia/i页面显示的是文字lt;igt;alt;/igt;而不是斜体——这是刻意为之可在 test.jsx 中看到对应测试核心逻辑在 lib/index.jsraw HTML 节点默认被转成文本展示。HTML 有三种处理方式方式效果适用场景默认不配置HTML 转义为纯文本展示渲染用户投稿最安全skipHtmlHTML 整段丢弃aib/ic→abc见 test.jsx完全不想保留 HTML加rehype-raw插件HTML 真正生效可信内容包体积 约 60kb✅ 最佳实践用户生成内容保持默认转义可信内容自家文档、CMS才上rehype-raw并搭配rehype-sanitize兜底详见 readme.md 的 Security 一节。坑 4表格、删除线、任务列表不显示——忘了装 GFM 插件react-markdown 默认只覆盖 CommonMark 基础语法。表格、删除线、任务列表、自动链接都是 GFM 扩展不装插件会原样显示~~删除线~~和| a | b |。✅ 最佳实践需要 GFM 语法就装remark-gfm并传入Markdown remarkPlugins{[remarkGfm]}{markdown}/Markdown插件要带选项时用[插件, 选项]数组形式传入。坑 5javascript:等危险链接被静默清空默认的defaultUrlTransform遵循 GitHub 的策略只放行http、https、irc、ircs、mailto、xmpp和相对路径其他协议一律置空——比如点我)会变成一个没有href的死链接。实现见 lib/index.js。⚠️ 注意不要为了省事把urlTransform改成放行一切那是直接打开 XSS 的口子。✅ 最佳实践保留默认值需要重写 URL如统一加 CDN 前缀时传入先调用默认逻辑再加工的函数。坑 6旧教程的属性名现在会直接报错react-markdown 从 v9 起移除了旧属性再传旧名字会直接抛错报错信息会明确提示该用什么替代。常见对照旧属性新属性sourcechildrenpluginsremarkPluginsrendererscomponentstransformLinkUri/transformImageUriurlTransform完整废弃清单见 lib/index.js 和 changelog.md。✅ 最佳实践网上教程多为旧版本编写升级 v10 时按上表改名自定义组件components还会额外收到一个node属性原始 AST 节点做语法高亮等增强时很实用。坑 7Markdown / MarkdownAsync / MarkdownHooks 三组件选错包内导出了三个组件见 index.js分工完全不同组件特点使用场景Markdown默认导出同步渲染绝大多数场景MarkdownAsync支持 async/await服务端渲染 异步插件MarkdownHooks基于 hooks首次渲染显示fallback客户端 异步插件✅ 最佳实践只用同步插件如remark-gfm就用默认Markdown必须用异步插件时按服务端 / 客户端二选一选错会导致插件根本不执行。一页速查症状 → 解决方案症状解决方案换行全部丢失Markdown 存进变量用{markdown}传入标题变成代码块内容顶格写去掉 4 空格缩进HTML 显示成div文本默认转义是安全行为可信内容用rehype-raw表格 / 删除线不渲染remarkPlugins{[remarkGfm]}外链点击无反应检查 URL 协议是否在白名单内升级后报 Unexpected prop按对照表改用新属性名相关资料完整文档与 APIreadme.md换行与缩进专题Appendix Creadme.mdHTML 处理专题Appendix Areadme.md核心渲染逻辑lib/index.js行为测试用例test.jsx版本与依赖信息package.json【免费下载链接】react-markdownMarkdown component for React项目地址: https://gitcode.com/gh_mirrors/re/react-markdown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考