Skip to main content

react-rendering

Render Markdown source or a MarkdownDocument with @tanstack/markdown/react using Markdown, renderMarkdownReact, component replacements, and React static SSR. Load for React article components, emitted-tag mappings, pre-parsed documents, custom elements, or renderer parity.

Informations de source

Dépôt
TanStack/markdown
Dernière activité de la source
1 octobre 2026 à 02:00
Langue détectée de SKILL.md
anglais
Étoiles
428
Forks
10

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
react-rendering
description
Render Markdown source or a MarkdownDocument with @tanstack/markdown/react using Markdown, renderMarkdownReact, component replacements, and React static SSR. Load for React article components, emitted-tag mappings, pre-parsed documents, custom elements, or renderer parity.
metadata
{"type":"framework","library":"@tanstack/markdown","framework":"react","library_version":"1.0.0"}
requires
["render-markdown"]
sources
["TanStack/markdown:docs/guides/react.md","TanStack/markdown:docs/reference/react.md","TanStack/markdown:docs/guides/extensions.md","TanStack/markdown:docs/core-concepts/security.md","TanStack/markdown:src/react.ts","TanStack/markdown:tests/ssr-react.test.tsx"]
This skill builds on [render-markdown](../render-markdown/SKILL.md). Read it first for the syntax profile, parser options, AST, and core trust boundaries. # React Rendering ## Setup Render source directly and keep the surrounding semantic element in the application: ```tsx import { Markdown } from '@tanstack/markdown/react' export function Article({ source }: { source: string }) { return ( <article> <Markdown>{source}</Markdown> </article> ) } ``` `Markdown` returns a React fragment. The React adapter requires React 18 or newer. ## Hooks and Components ### Replace emitted links with an application component ```tsx import { Markdown, type MarkdownComponents, } from '@tanstack/markdown/react' const components = { a(props) { const external = props.href?.startsWith('http') ?? false return ( <a {...props} rel={external ? 'nofollow noopener noreferrer' : props.rel} target={external ? '_blank' : props.target} /> ) }, } satisfies MarkdownComponents export function Article({ source }: { source: string }) { return ( <article> <Markdown components={components}>{source}</Markdown> </article> ) } ``` Known intrinsic keys infer their matching React props. Arbitrary extension component tag names remain supported. ### Parse once before repeated React rendering ```tsx import { parseMarkdown } from '@tanstack/markdown/parser' import { Markdown } from '@tanstack/markdown/react' const document = parseMarkdown('# Cached article\n\nRendered from an AST.') export function Article() { return ( <article> <Markdown>{document}</Markdown> </article> ) } ``` Apply parser options and document transforms when creating the document; renderer options cannot retroactively change its structure. ### Render static React markup on the server ```tsx import { renderToStaticMarkup } from 'react-dom/server' import { Markdown } from '@tanstack/markdown/react' const source = '# Server-rendered article' export const html = renderToStaticMarkup( <article> <Markdown>{source}</Markdown> </article>, ) ``` Core static output is tested for structural equivalence with `renderHtml()`. ### Compose through the lower-level node API ```tsx import type { ReactNode } from 'react' import { parseMarkdown } from '@tanstack/markdown/parser' import { renderMarkdownReact } from '@tanstack/markdown/react' const document = parseMarkdown('# Parsed once') export function ArticleBody(): ReactNode { return renderMarkdownReact(document) } ``` Use `renderBlockReact` or `renderInlineReact` only when custom tree composition needs individual public AST nodes. ## Common Mistakes ### HIGH Injecting HTML instead of React nodes Wrong: ```tsx import { renderHtml } from '@tanstack/markdown' export function Article({ source }: { source: string }) { const html = renderHtml(source) return <article dangerouslySetInnerHTML={{ __html: html }} /> } ``` Correct: ```tsx import { Markdown } from '@tanstack/markdown/react' export function Article({ source }: { source: string }) { return ( <article> <Markdown>{source}</Markdown> </article> ) } ``` The HTML-string path bypasses React component replacement and creates an unnecessary trusted-HTML boundary. Source: `docs/guides/react.md` ### HIGH Mapping AST node names instead of tags Wrong: ```tsx import type { ComponentProps } from 'react' import { Markdown } from '@tanstack/markdown/react' function ArticleLink(props: ComponentProps<'a'>) { return <a {...props} data-navigation="article" /> } export function Article() { return ( <Markdown components={{ link: ArticleLink }}> {'Read the [guide](/guide).'} </Markdown> ) } ``` Correct: ```tsx import type { ComponentProps } from 'react' import { Markdown } from '@tanstack/markdown/react' function ArticleLink(props: ComponentProps<'a'>) { return <a {...props} data-navigation="article" /> } export function Article() { return ( <Markdown components={{ a: ArticleLink }}> {'Read the [guide](/guide).'} </Markdown> ) } ``` The map is keyed by emitted tag names such as `a`, not AST discriminants such as `link`. Source: `docs/guides/react.md` ### HIGH Expecting HTML extension hooks in React Wrong: ```tsx import type { MarkdownExtension } from '@tanstack/markdown' import { Markdown } from '@tanstack/markdown/react' const paragraphHtml: MarkdownExtension = { name: 'paragraph-html', renderHtml(node) { return node.type === 'paragraph' ? '<aside>Rendered only by the HTML renderer</aside>' : undefined }, } export function Article() { return <Markdown extensions={[paragraphHtml]}>Ordinary content</Markdown> } ``` Correct: ```tsx import type { MarkdownExtension } from '@tanstack/markdown' import type { PropsWithChildren } from 'react' import { Markdown } from '@tanstack/markdown/react' const panelExtension: MarkdownExtension = { name: 'panel', transformDocument(document) { return { ...document, children: [ { type: 'component', name: 'panel', tagName: 'doc-panel', attributes: {}, children: document.children, }, ], } }, } function Panel({ children }: PropsWithChildren) { return <aside className="documentation-panel">{children}</aside> } export function Article() { return ( <Markdown components={{ 'doc-panel': Panel }} extensions={[panelExtension]} > Ordinary content </Markdown> ) } ``` `MarkdownExtension.renderHtml` is HTML-specific; portable custom output uses `ComponentNode` and an emitted-tag component mapping. Source: `docs/guides/extensions.md` ### CRITICAL Enabling raw HTML for untrusted input Wrong: ```tsx import { Markdown } from '@tanstack/markdown/react' export function UserPost({ source }: { source: string }) { return <Markdown allowHtml>{source}</Markdown> } ``` Correct: ```tsx import { Markdown } from '@tanstack/markdown/react' export function UserPost({ source }: { source: string }) { return <Markdown>{source}</Markdown> } ``` With `allowHtml`, React uses `dangerouslySetInnerHTML`; TanStack Markdown does not sanitize that raw HTML. Source: `docs/core-concepts/security.md` ### HIGH Tension: renderer parity versus React customization Core React SSR is tested against `renderHtml()`. React component replacements, raw HTML, highlighter output, and HTML-only extension hooks are application-controlled boundaries outside that parity guarantee. See also: [custom-extensions](../custom-extensions/SKILL.md) for portable `ComponentNode` output. ## Cross-References - [render-markdown](../render-markdown/SKILL.md) - shared `MarkdownInput`, parser options, AST behavior, and syntax profile. - [custom-extensions](../custom-extensions/SKILL.md) - emit custom tags that React can replace through `components`. - [production-pipelines](../production-pipelines/SKILL.md) - audit raw HTML, highlighter output, untrusted content, and SSR boundaries.
Voir sur GitHub