Skip to main content

Tutorial Docusaurus React Live

· 4 min read
Docux
Curious explorer, a bit of a mad experimenter, and a bit of a contributor.

1. Why a playground?

Readers learn faster when they can modify an example inline. The @docusaurus/theme-live-codeblock theme integrates react-live to evaluate JSX in real time.

Benefits:

  • Instant feedback
  • Pedagogical demos without an external sandbox
  • Visual consistency with your site
  • No page context switching

2. Install the live theme

npm install @docusaurus/theme-live-codeblock --save

Ensure all @docusaurus/* versions are aligned (e.g. 3.9.1).

3. Configure docusaurus.config.js

Add (or extend) the themes key:

docusaurus.config.js
export default {
// ...other options
themes: [
'@docusaurus/theme-live-codeblock'
],
};

Optional: adjust styling with custom CSS (Infima is bundled).

4. Create your first jsx live blocks

A MDX fenced block becomes interactive by adding live after the language:

```jsx live
() => <button style={{padding:8}}>Click me</button>
```

You can also write a function:

```jsx live
function Counter(){
const [n,setN] = React.useState(0);
return <button onClick={()=>setN(n+1)}>Count: {n}</button>;
}
<Counter />
```

5. Effective patterns

PatternUse caseBenefitExample
Final expressionTiny demoUltra concise(<Badge>Hi</Badge>)
Const + final identifierReadable snippetShows valueconst el=<div/>; el
Function + callInternal logicReusablefunction Demo(){...}; <Demo />
Inline hooksSmall interactionsDirectconst [x,setX]=useState(0); <button onClick={()=>setX(x+1)}>{x}
Export default (avoid)Legacy habitNoise here(do not use)

Key rule: the last expression of the block is rendered (no export).

6. Swizzle ReactLiveScope

Problem: inside a live block, your custom components (Tooltip, LogoIcon, etc.) are not known by default.

Solution: create src/theme/ReactLiveScope/index.js to inject a global scope.

src/theme/ReactLiveScope/index.js

import * as React from 'react';

import Tooltip from '@site/src/components/Tooltip';
import LogoIcon from '@site/src/components/LogoIcon';
import Skill from '@site/src/components/Skill';
import Contributor from '@site/src/components/Contributor';

// Export only the symbols the react-live runtime needs to evaluate snippets.
const {
useState,
useEffect,
useRef,
useMemo,
useCallback,
Fragment,
forwardRef,
createElement,
Children,
} = React;

export default {
// Garder l'objet React complet accessible si besoin (sans le spread pour éviter la clé 'default')
React,
// Hooks fréquemment utilisés dans les snippets
useState,
useEffect,
useRef,
useMemo,
useCallback,
Fragment,
forwardRef,
createElement,
Children,
// Composants custom exposés dans les blocs live
Tooltip,
LogoIcon,
Skill,
Contributor,
};

From there on:

Live Editor

	<Tooltip model="teacher" text="DocuxLab">
		Swizzle ready!
	</Tooltip>

Result
Loading...

7. Advanced examples: interactive Tooltip

Simple model

Live Editor

	<Tooltip text="Simple tooltip">Short content.</Tooltip>

Result
Loading...

Two tooltips side by side

Live Editor

	<div style={{display:'flex', gap:16}}>
		<Tooltip model="teacher" text="Teacher">
			Example with model.
		</Tooltip>
		<Tooltip model="suricate" text="Pépé" position="bottom">
			Bottom position.
		</Tooltip>
	</div>

Result
Loading...

Skill (progress bar)

Live Editor
<div style={{display:'flex', flexDirection:'column', gap:8}}>
	<Skill name={<><LogoIcon name="react" size='24' /> React</>} value={88} type="bar" color="#61DAFB" height={25} />
	<Skill name={<><LogoIcon name="vue" size='24' /> Vue.js</>} value={75} type="bar" color="#4FC08D" height={25} />
	<Skill name={<><LogoIcon name="nodejs" size='24' /> Node.js</>} value={82} type="bar" color="#339933" height={25} />
	<Skill name={<><LogoIcon name="python" size='24' /> Python</>} value={78} type="bar" color="#3776AB" height={25} />
</div>

Result
Loading...

Skill (animated circle)

Live Editor
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))', gap: '20px', marginTop: '20px'}}>
  <Skill name={<><LogoIcon name="html-5" size='24' /> </>} value={95} type="circle" color="#E34F26" valuePosition="center" size={100} />
  <Skill name={<><LogoIcon name="css-3" size='24' /> </>} value={90} type="circle" color="#1572B6" valuePosition="center" size={100} />
  <Skill name={<><LogoIcon name="javascript" size='24' /> </>} value={85} type="circle" color="#F7DF1E" valuePosition="center" size={100} />
  </div>
Result
Loading...

Contributor (card)

Live Editor

	<Contributor
		name="Docux"
		github="Juniors017"
		website="https://github.com/Juniors017"
		avatarUrl="/img/docux.png"
		components={['Tooltip','Skill','etc...']}
		description="Author of several UI components for this site."
        
	/>

Result
Loading...

LogoIcon (variants)

Live Editor

	<div style={{display:'flex',gap:24,alignItems:'center'}}>
		<LogoIcon name="docusaurus" size={40} />
		<LogoIcon name="javascript" size={40} />
		<LogoIcon name="css-3" size={40} />
	</div>

Result
Loading...

8. Best practices

  • Keep snippets short and progressive.
  • Do not overload the scope (clarity + performance).
  • Watch for CSS collisions (avoid heavy globals).
  • Prefer an explicit final expression for readability.
  • Update @docusaurus/* dependencies together.

9. Quick debugging

IssueLikely causeFix
X is not definedComponent not in scopeAdd to ReactLiveScope
Nothing displayedNo final expressionEnd with JSX or identifier
React import crashUnnecessary importRemove import React
Broken styleInfima/custom conflictWrap / isolate
Versions mismatchMisaligned packagesAlign versions

10. Going further

Ideas:

  • Add a light/dark theme toggle inside demos.
  • Persist state (localStorage) in a live block.
  • Generate dynamic component variations.
Your turn!

No related posts.

Retour en haut