Overview
The components property is the primary extension point in @ant-design/x-markdown. It lets you map Markdown/HTML nodes to your own React components so you can control rendering, streaming behavior, and business data interaction in one place. To extend further, see Plugins and custom renderers.
import React from 'react';import { Mermaid, Think, XMarkdown } from '@ant-design/x';<XMarkdowncomponents={{think: Think,mermaid: Mermaid,}}/>;
| Property | Description | Type | Default |
|---|---|---|---|
| domNode | Component DOM node from html-react-parser, containing parsed DOM node information | DOMNode | - |
| streamStatus | Streaming rendering supports two states: loading indicates content is being loaded, done indicates loading is complete. Currently only supports HTML format and fenced code blocks. Since indented code has no clear end marker, it always returns done status | 'loading' | 'done' | - |
| children | Content wrapped in the component, containing the text content of DOM nodes | React.ReactNode | - |
| rest | Component properties, supports all standard HTML attributes (such as href, title, className, etc.) and custom data attributes | Record<string, any> | - |
Custom components often need business data (theme, callbacks, etc.). Passing it via an inline function creates a new component reference on every render, so React unmounts and remounts the whole subtree — losing internal state and hurting performance in streaming scenarios. Use componentsProps to pass extra props while keeping component references stable:
import React, { useMemo } from 'react';import { XMarkdown } from '@ant-design/x';// ❌ Inline function: a new component type every render, the subtree is rebuilt<XMarkdowncomponents={{'custom-chart': (props) => <CustomChart {...props} theme={theme} onSelect={onSelect} />,}}/>;// ✅ Stable component reference; extra data flows through componentsPropsconst components = { 'custom-chart': CustomChart };const componentsProps = useMemo(() => ({ 'custom-chart': { theme, onSelect } }), [theme, onSelect]);<XMarkdown components={components} componentsProps={componentsProps} />;
componentsProps is keyed by tag name. Its props are merged with the parsed HTML attributes and passed to the component:
componentsProps wins — a title in componentsProps overrides title="..." from the HTML.className / class is the exception: both sides are concatenated, with the componentsProps class name first.domNode, streamStatus, children (plus lang and block for code) — cannot be overridden and are ignored if present in componentsProps.When componentsProps changes, the component receives a normal props update without being remounted. Like components, it takes part in the render cache, so passing an inline object literal invalidates that cache on every render and re-parses the whole tree — keep the reference stable with useMemo as shown above.
components; use componentsProps to pass extra data.streamStatus to separate loading UI (loading) from finalized UI (done).streamStatus === 'done'.If block-level custom tags contain unexpected blank lines, Markdown parsers may end the HTML block early and convert trailing content into paragraphs. To avoid this: