mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-16 10:37:20 +02:00
chore: prepare v2.0.0-beta.16 release (#6760)
This commit is contained in:
parent
17b8eded79
commit
124511f445
142 changed files with 6743 additions and 4173 deletions
|
@ -0,0 +1,465 @@
|
|||
---
|
||||
id: react
|
||||
title: MDX and React
|
||||
description: Using the power of React in Docusaurus Markdown documents, thanks to MDX
|
||||
slug: /markdown-features/react
|
||||
---
|
||||
|
||||
# MDX and React
|
||||
|
||||
```mdx-code-block
|
||||
import BrowserWindow from '@site/src/components/BrowserWindow';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import styles from './markdown-features-react.module.css';
|
||||
```
|
||||
|
||||
## Using JSX in Markdown {#using-jsx-in-markdown}
|
||||
|
||||
Docusaurus has built-in support for [MDX v1](https://mdxjs.com/), which allows you to write JSX within your Markdown files and render them as React components.
|
||||
|
||||
:::note
|
||||
|
||||
While Docusaurus parses both `.md` and `.mdx` files using MDX, some of the syntaxes are treated slightly differently by third-party tools. For the most accurate parsing and better editor support, we recommend using the `.mdx` extension for files containing MDX syntax.
|
||||
|
||||
:::
|
||||
|
||||
To define any custom component within an MDX file, you have to export it.
|
||||
|
||||
```jsx
|
||||
export const Highlight = ({children, color}) => (
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
borderRadius: '2px',
|
||||
color: '#fff',
|
||||
padding: '0.2rem',
|
||||
}}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
|
||||
<Highlight color="#25c2a0">Docusaurus green</Highlight> and <Highlight color="#1877F2">Facebook blue</Highlight> are my favorite colors.
|
||||
|
||||
I can write **Markdown** alongside my _JSX_!
|
||||
```
|
||||
|
||||
Notice how it renders both the markup from your React component and the Markdown syntax:
|
||||
|
||||
```mdx-code-block
|
||||
export const Highlight = ({children, color}) => (
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
borderRadius: '2px',
|
||||
color: '#fff',
|
||||
padding: '0.2rem',
|
||||
}}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
|
||||
<BrowserWindow minHeight={240}>
|
||||
|
||||
<Highlight color="#25c2a0">Docusaurus green</Highlight>
|
||||
{` `}and <Highlight color="#1877F2">Facebook blue</Highlight> are my favorite colors.
|
||||
|
||||
I can write **Markdown** alongside my _JSX_!
|
||||
|
||||
</BrowserWindow>
|
||||
```
|
||||
|
||||
:::caution MDX is JSX
|
||||
|
||||
Since all doc files are parsed using MDX, anything that looks like HTML is actually JSX. Therefore, if you need to inline-style a component, follow JSX flavor and provide style objects.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx
|
||||
/* Instead of this: */
|
||||
<span style="background-color: red">Foo</span>
|
||||
/* Use this: */
|
||||
<span style={{backgroundColor: 'red'}}>Foo</span>
|
||||
```
|
||||
|
||||
This behavior is different from Docusaurus 1. See also [Migrating from v1 to v2](../../migration/migration-manual.md#convert-style-attributes-to-style-objects-in-mdx).
|
||||
|
||||
In addition, MDX is not [100% compatible with CommonMark](https://github.com/facebook/docusaurus/issues/3018). Use the **[MDX playground](https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/playground)** to ensure that your syntax is valid MDX.
|
||||
|
||||
:::
|
||||
|
||||
### Importing components {#importing-components}
|
||||
|
||||
You can also import your own components defined in other files or third-party components installed via npm.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```md
|
||||
<!-- Docusaurus theme component -->
|
||||
import TOCInline from '@theme/TOCInline';
|
||||
<!-- External component -->
|
||||
import Button from '@mui/material/Button';
|
||||
<!-- Custom component -->
|
||||
import BrowserWindow from '@site/src/components/BrowserWindow';
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
||||
The `@site` alias points to your website's directory, usually where the `docusaurus.config.js` file is. Using an alias instead of relative paths (`'../../src/components/BrowserWindow'`) saves you from updating import paths when moving files around, or when [versioning docs](../docs/versioning.md) and [translating](../../i18n/i18n-tutorial.md).
|
||||
|
||||
:::
|
||||
|
||||
While declaring components within Markdown is very convenient for simple cases, it becomes hard to maintain because of limited editor support, risks of parsing errors, and low reusability. Use a separate `.js` file when your component involves complex JS logic:
|
||||
|
||||
```jsx title="src/components/Highlight.js"
|
||||
export default function Highlight({children, color}) {
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
borderRadius: '2px',
|
||||
color: '#fff',
|
||||
padding: '0.2rem',
|
||||
}}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```md title="markdown-file.mdx"
|
||||
import Highlight from '@site/src/components/Highlight';
|
||||
|
||||
<Highlight color="#25c2a0">Docusaurus green</Highlight>
|
||||
```
|
||||
|
||||
Check out the [MDX docs](https://mdxjs.com/) to see what other fancy stuff you can do with MDX.
|
||||
|
||||
### Markdown and JSX interoperability {#markdown-and-jsx-interoperability}
|
||||
|
||||
Docusaurus v2 is using MDX v1, which has a lot of known cases where the content fails to be correctly parsed as Markdown. Use the **[MDX playground](https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/playground)** to ensure that your syntax is valid MDX.
|
||||
|
||||
````mdx-code-block
|
||||
<details>
|
||||
|
||||
<summary>Samples of parsing failures</summary>
|
||||
|
||||
**A paragraph starting with a JSX tag will be seen entirely as a JSX string:**
|
||||
|
||||
<Tabs groupId="jsx-and-md">
|
||||
<TabItem value="Problem">
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<span style={{color: 'red'}}>Highlighted text</span> but afterwards _Markdown_ **doesn't work**
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
|
||||
<span style={{color: 'red'}}>Highlighted text</span> but afterwards _Markdown_ **doesn't work**
|
||||
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
</TabItem>
|
||||
<TabItem value="Workaround">
|
||||
|
||||
Use JSX for the rest of the line, or prefix the line with some plain text:
|
||||
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<span style={{color: 'red'}}>Use JSX for the paragraph</span> to stop <i>worrying about</i> <b>Markdown</b>
|
||||
|
||||
​<span style={{color: 'red'}}>← This is a zero-width space</span> and afterwards <i>Markdown</i> <b>works</b>
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
|
||||
<span style={{color: 'red'}}>Use JSX for the paragraph</span> to stop <i>worrying about</i> <b>Markdown</b>
|
||||
|
||||
​<span style={{color: 'red'}}>← This is a zero-width space</span> and afterwards <i>Markdown</i> <b>works</b>
|
||||
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**Markdown within a JSX tag never works:**
|
||||
|
||||
<Tabs groupId="jsx-and-md">
|
||||
<TabItem value="Problem">
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<span style={{color: 'red'}}>**Bold doesn't work**</span>
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
|
||||
<span style={{color: 'red'}}>**Bold doesn't work**</span>
|
||||
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Workaround">
|
||||
|
||||
Use JSX within JSX tag, or move the Markdown to the outer layer:
|
||||
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<span style={{color: 'red'}}><b>Bold now works</b></span>
|
||||
|
||||
**<span style={{color: 'red'}}>Bold now works</span>**
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
|
||||
<span style={{color: 'red'}}><b>Bold now works</b></span>
|
||||
|
||||
**<span style={{color: 'red'}}>Bold now works</span>**
|
||||
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**Text immediately below a JSX tag will be seen as JSX text:**
|
||||
|
||||
<Tabs groupId="jsx-and-md">
|
||||
<TabItem value="Problem">
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<div style={{color: 'red'}}>
|
||||
**Bold still doesn't work**
|
||||
</div>
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
|
||||
<div style={{color: 'red'}}>
|
||||
**Bold still doesn't work**
|
||||
</div>
|
||||
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
</TabItem>
|
||||
<TabItem value="Workaround">
|
||||
|
||||
Add an empty new line:
|
||||
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<div style={{color: 'red'}}>
|
||||
|
||||
**Bold now works**
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
<div style={{color: 'red'}}>
|
||||
|
||||
**Bold now works**
|
||||
|
||||
</div>
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**Markdown text indented by four spaces will be seen as a code block:**
|
||||
|
||||
<Tabs groupId="jsx-and-md">
|
||||
<TabItem value="Problem">
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<div style={{color: 'red'}}>
|
||||
|
||||
You may think I'm just some text...
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
|
||||
<div style={{color: 'red'}}>
|
||||
|
||||
You may think I'm just some text...
|
||||
|
||||
</div>
|
||||
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
</TabItem>
|
||||
<TabItem value="Workaround">
|
||||
|
||||
Don't indent:
|
||||
|
||||
<div className={styles.wrappingBlock}>
|
||||
|
||||
```jsx
|
||||
<div style={{color: 'red'}}>
|
||||
|
||||
Now I'm actually just text
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
</div>
|
||||
<div className={styles.wrappingBlock}>
|
||||
<BrowserWindow>
|
||||
<div style={{color: 'red'}}>
|
||||
|
||||
Now I'm actually just text
|
||||
|
||||
</div>
|
||||
</BrowserWindow>
|
||||
</div>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
</details>
|
||||
````
|
||||
|
||||
## Importing code snippets {#importing-code-snippets}
|
||||
|
||||
You can not only import a file containing a component definition, but also import any code file as raw text, and then insert it in a code block, thanks to [Webpack raw-loader](https://webpack.js.org/loaders/raw-loader/). In order to use `raw-loader`, you first need to install it in your project:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install --save raw-loader
|
||||
```
|
||||
|
||||
Now you can import code snippets from another file as it is:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```jsx title="myMarkdownFile.mdx"
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MyComponentSource from '!!raw-loader!./myComponent';
|
||||
|
||||
<CodeBlock className="language-jsx">{MyComponentSource}</CodeBlock>
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
```mdx-code-block
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MyComponentSource from '!!raw-loader!@site/src/pages/examples/_myComponent';
|
||||
|
||||
<BrowserWindow>
|
||||
|
||||
<CodeBlock className="language-jsx">{MyComponentSource}</CodeBlock>
|
||||
|
||||
</BrowserWindow>
|
||||
|
||||
<br />
|
||||
```
|
||||
|
||||
See [using code blocks in JSX](./markdown-features-code-blocks.mdx#usage-in-jsx) for more details of the `<CodeBlock>` component.
|
||||
|
||||
:::note
|
||||
|
||||
You have to use `<CodeBlock>` rather than the Markdown triple-backtick ` ``` `, because the latter will ship out any of its content as-is, but you want to interpolate the imported text here.
|
||||
|
||||
:::
|
||||
|
||||
:::warning
|
||||
|
||||
This feature is experimental and might be subject to breaking API changes in the future.
|
||||
|
||||
:::
|
||||
|
||||
## Importing Markdown {#importing-markdown}
|
||||
|
||||
You can use Markdown files as components and import them elsewhere, either in Markdown files or in React pages.
|
||||
|
||||
By convention, using the **`_` filename prefix** will not create any doc page and means the markdown file is a **"partial"**, to be imported by other files.
|
||||
|
||||
```md title="_markdown-partial-example.mdx"
|
||||
<span>Hello {props.name}</span>
|
||||
|
||||
This is text some content from `_markdown-partial-example.mdx`.
|
||||
```
|
||||
|
||||
```jsx title="someOtherDoc.mdx"
|
||||
import PartialExample from './_markdown-partial-example.mdx';
|
||||
|
||||
<PartialExample name="Sebastien" />;
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
import PartialExample from './_markdown-partial-example.mdx';
|
||||
|
||||
<BrowserWindow>
|
||||
<PartialExample name="Sebastien" />
|
||||
</BrowserWindow>
|
||||
|
||||
<br />
|
||||
```
|
||||
|
||||
This way, you can reuse content among multiple pages and avoid duplicating materials.
|
||||
|
||||
:::caution
|
||||
|
||||
The table of contents does not currently contain the imported Markdown headings. This is a technical limitation that we are trying to solve ([issue](https://github.com/facebook/docusaurus/issues/3915)).
|
||||
|
||||
:::
|
||||
|
||||
## Available exports {#available-exports}
|
||||
|
||||
Within the MDX page, the following variables are available as globals:
|
||||
|
||||
- `frontMatter`: the front matter as a record of string keys and values;
|
||||
- `toc`: the table of contents, as a tree of headings. See also [Inline TOC](./markdown-features-inline-toc.mdx) for a more concrete use-case.
|
||||
- `contentTitle`: the Markdown title, which is the first `h1` heading in the Markdown text. It's `undefined` if there isn't one (e.g. title specified in the front matter).
|
||||
|
||||
```jsx
|
||||
import TOCInline from '@theme/TOCInline';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
The table of contents for this page, serialized:
|
||||
|
||||
<CodeBlock className="language-json">{JSON.stringify(toc, null, 2)}</CodeBlock>
|
||||
|
||||
The front matter of this page:
|
||||
|
||||
<ul>
|
||||
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
|
||||
</ul>
|
||||
|
||||
<p>The title of this page is: <b>{contentTitle}</b></p>
|
||||
```
|
||||
|
||||
```mdx-code-block
|
||||
import TOCInline from '@theme/TOCInline';
|
||||
|
||||
<BrowserWindow>
|
||||
|
||||
The table of contents for this page, serialized:
|
||||
|
||||
<CodeBlock className="language-json">{JSON.stringify(toc, null, 2)}</CodeBlock>
|
||||
|
||||
The front matter of this page:
|
||||
|
||||
<ul>
|
||||
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
|
||||
</ul>
|
||||
|
||||
<p>The title of this page is: <b>{contentTitle}</b></p>
|
||||
|
||||
</BrowserWindow>
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue