Files
mintlify__docs/zh/customize/react-components.mdx
mintlify[bot] 4fc8d5e910 docs: sync react-components lazy loading updates to es/fr/zh (#6458)
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
2026-07-08 22:48:35 +00:00

217 lines
7.1 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "React"
description: "使用 JSX、状态和客户端逻辑在你的 Mintlify 文档中通过自定义 React 组件构建交互且可复用的元素。"
keywords: ["React 组件", "交互式组件", "JSX", "自定义组件"]
boost: 3
---
import { ColorGenerator } from "/snippets/color-generator.jsx";
直接在 MDX 文件中使用 [React 组件](https://react.dev) 和 [hooks](https://react.dev/reference/react/hooks) 在文档中构建交互式元素。
<div id="inline-components">
## 内联组件
</div>
直接在你的 MDX 文件中声明组件:
export const Counter = () => {
const [count, setCount] = useState(0)
const increment = () => setCount(count + 1)
const decrement = () => setCount(count - 1)
return (
<div className="flex items-center justify-center">
<div className="flex items-center rounded-xl overflow-hidden border border-zinc-950/20 dark:border-white/20">
<button
onClick={decrement}
className="flex items-center justify-center h-8 w-8 text-zinc-950/80 dark:text-white/80 border-r border-zinc-950/20 dark:border-white/20"
aria-label="Decrease"
>
-
</button>
<div className="flex text-sm items-center justify-center h-8 px-6 text-zinc-950/80 dark:text-white/80 font-medium min-w-[4rem] text-center">
{count}
</div>
<button
onClick={increment}
className="flex items-center justify-center h-8 w-8 text-zinc-950/80 dark:text-white/80 border-l border-zinc-950/20 dark:border-white/20"
aria-label="Increase"
>
+
</button>
</div>
</div>
)
}
<Counter />
```mdx
export const Counter = () => {
const [count, setCount] = useState(0)
const increment = () => setCount(count + 1)
const decrement = () => setCount(count - 1)
return (
<div>
<button onClick={decrement}>-</button>
<span>{count}</span>
<button onClick={increment}>+</button>
</div>
)
}
<Counter />
```
<div id="import-components">
## 导入组件
</div>
组件文件必须位于 `/snippets/` 文件夹中。更多信息请参阅 [可复用片段](/zh/create/reusable-snippets)。
<Note>
不支持嵌套导入。请将所有被引用的组件直接导入到父 MDX 文件中。
</Note>
在 `snippets/` 中创建一个组件文件:
```mdx /snippets/color-generator.jsx [expandable]
export const ColorGenerator = () => {
const [hue, setHue] = useState(180)
const [saturation, setSaturation] = useState(50)
const [lightness, setLightness] = useState(50)
const [colors, setColors] = useState([])
useEffect(() => {
const newColors = []
for (let i = 0; i < 5; i++) {
const l = Math.max(10, Math.min(90, lightness - 20 + i * 10))
newColors.push(`hsl(${hue}, ${saturation}%, ${l}%)`)
}
setColors(newColors)
}, [hue, saturation, lightness])
const copyToClipboard = (color) => {
navigator.clipboard
.writeText(color)
.then(() => {
console.log(`Copied ${color} to clipboard!`)
})
.catch((err) => {
console.error("Failed to copy: ", err)
})
}
return (
<div className="p-4 border dark:border-zinc-950/80 rounded-xl not-prose">
<div className="space-y-4">
<div className="space-y-2">
<label className="block text-sm text-zinc-950/70 dark:text-white/70">
Hue: {hue}°
<input
type="range"
min="0"
max="360"
value={hue}
onChange={(e) => setHue(Number.parseInt(e.target.value))}
className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
style={{
background: `linear-gradient(to right,
hsl(0, ${saturation}%, ${lightness}%),
hsl(60, ${saturation}%, ${lightness}%),
hsl(120, ${saturation}%, ${lightness}%),
hsl(180, ${saturation}%, ${lightness}%),
hsl(240, ${saturation}%, ${lightness}%),
hsl(300, ${saturation}%, ${lightness}%),
hsl(360, ${saturation}%, ${lightness}%))`,
}}
/>
</label>
<label className="block text-sm text-zinc-950/70 dark:text-white/70">
Saturation: {saturation}%
<input
type="range"
min="0"
max="100"
value={saturation}
onChange={(e) => setSaturation(Number.parseInt(e.target.value))}
className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
style={{
background: `linear-gradient(to right,
hsl(${hue}, 0%, ${lightness}%),
hsl(${hue}, 50%, ${lightness}%),
hsl(${hue}, 100%, ${lightness}%))`,
}}
/>
</label>
<label className="block text-sm text-zinc-950/70 dark:text-white/70">
Lightness: {lightness}%
<input
type="range"
min="0"
max="100"
value={lightness}
onChange={(e) => setLightness(Number.parseInt(e.target.value))}
className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
style={{
background: `linear-gradient(to right,
hsl(${hue}, ${saturation}%, 0%),
hsl(${hue}, ${saturation}%, 50%),
hsl(${hue}, ${saturation}%, 100%))`,
}}
/>
</label>
</div>
<div className="flex space-x-1">
{colors.map((color, idx) => (
<div
key={idx}
className="h-16 rounded flex-1 cursor-pointer transition-transform hover:scale-105"
style={{ backgroundColor: color }}
title={`Click to copy: ${color}`}
onClick={() => copyToClipboard(color)}
/>
))}
</div>
<div className="text-sm font-mono text-zinc-950/70 dark:text-white/70">
<p>
Base color: hsl({hue}, {saturation}%, {lightness}%)
</p>
</div>
</div>
</div>
)
}
```
然后导入并使用它:
```mdx
import { ColorGenerator } from "/snippets/color-generator.jsx"
<ColorGenerator />
```
<ColorGenerator />
<div id="considerations">
## 注意事项
</div>
- **SEO**:搜索引擎可能无法完全索引由客户端渲染的动态内容。
- **首次加载**:访客在组件渲染之前可能会看到闪烁。
- **可访问性**:确保屏幕阅读器能够播报动态内容的变化。
- **优化依赖数组**:仅在 `useEffect` 中包含必要的依赖。
- **缓存昂贵操作**:在适当之处使用 `useMemo` 或 `useCallback`。
- **减少重新渲染**:将大型组件拆分为较小的组件。
- **懒加载**:组件代码无法懒加载。所有组件都会随页面一起加载。如果某个组件在挂载时会执行资源密集型操作(例如获取数据或进行大量计算),请使用条件渲染,将其挂载推迟到用户交互时。