Componentes React personalizados
Puedes definir componentes React personalizados directamente en tus archivos MDX, lo que te da control total sobre la presentación de tu contenido.
Define componentes React personalizados directamente en archivos MDX. Exporta un componente de función de flecha al principio del archivo y úsalo en línea. Los componentes se renderizan en el servidor durante el build con acceso a todos los componentes integrados de Jamdesk y las clases de Tailwind.
Las capturas de pantalla muestran la interfaz en inglés.
Uso básico
Define un componente usando export const al principio de tu archivo MDX:
export const Highlight = ({ children, color }) => (
<span style={{ backgroundColor: color, padding: '0.2em 0.4em', borderRadius: '4px' }}>
{children}
</span>
);
This text has a <Highlight color="#ffeb3b">yellow highlight</Highlight> in it.
Los nombres de los componentes deben usar PascalCase (comenzar con una letra mayúscula).
Ejemplo: tarjeta hero
Aquí hay un ejemplo más complejo con múltiples props y clases de Tailwind:
export const HeroCard = ({ title, description, href, icon }) => (
<a
href={href}
className="group block p-6 rounded-lg border border-gray-200 hover:border-blue-500 transition-colors"
>
<div className="flex items-center gap-3 mb-2">
<Icon icon={icon} />
<h3 className="font-semibold text-lg">{title}</h3>
</div>
<p className="text-gray-600">{description}</p>
</a>
);
<div className="grid grid-cols-2 gap-4">
<HeroCard
title="Getting started"
description="Learn the basics"
href="/quickstart"
icon="rocket"
/>
<HeroCard
title="Components"
description="Explore available components"
href="/components/overview"
icon="puzzle-piece"
/>
</div>
Usar componentes integrados
Tus componentes personalizados tienen acceso a todos los componentes integrados de Jamdesk. No se necesitan imports:
export const FeatureCard = ({ title, children }) => (
<Card title={title} icon="star">
{children}
<Tip>This tip is inside a custom component!</Tip>
</Card>
);
<FeatureCard title="My Feature">
<Note>Notes work inside custom components too!</Note>
</FeatureCard>
Componentes integrados por categoría:
| Categoría | Componentes |
|---|---|
| Llamadas | Note, Tip, Info, Warning, Check, Danger |
| Diseño | Card, Columns, Tabs, Tab, Accordion, Steps, Step, View |
| Medios | Frame, Icon, Badge, Tooltip |
| Código | CodeGroup |
| Docs de API | ParamField, ResponseField, Expandable |
Limitaciones
- Solo funciones de flecha: Usa la sintaxis
export const. La sintaxisexport functionno es compatible. - Sin imports: No puedes importar paquetes externos ni otros archivos
- Sin hooks: Los hooks de React (
useState,useEffect,useRef, etc.) no están disponibles. Los componentes se renderizan en el servidor durante el build, y los hooks solo funcionan en el cliente. Para componentes interactivos, usa archivos de snippets en su lugar (ver solución de problemas a continuación). - Solo servidor: Los componentes se renderizan en el servidor; no hay interactividad del lado del cliente ni controladores de eventos
- Solo Tailwind: Usa clases de Tailwind CSS para estilos; CSS-in-JS no está disponible
- Sintaxis estricta: Los errores de sintaxis en los componentes en línea fallarán el build con un mensaje de error claro
- Nombres en PascalCase: Los nombres de los componentes deben comenzar con una letra mayúscula y contener solo letras y números (sin guiones bajos)
¿Necesitas hooks de React? Los componentes en línea no pueden usar useState, useEffect u otros hooks porque se renderizan en el servidor durante el build. Para componentes interactivos que necesiten estado o efectos, crea un archivo de snippet con la directiva 'use client' (ver la sección de solución de problemas a continuación).
Mejores prácticas
Los componentes en línea deben ser presentacionales. Para lógica compleja, solicita un componente integrado.
Asegúrate de que tus componentes sean accesibles con los elementos HTML adecuados y atributos ARIA.
Previsualiza tu documentación localmente para verificar que los componentes se rendericen correctamente en los modos claro y oscuro.
Solución de problemas
Error: Expected component 'MyComponent' to be defined
Causas:
- El nombre del componente no usa PascalCase (debe comenzar con letra mayúscula)
- Error de sintaxis en la definición del componente
- Etiqueta de cierre o paréntesis faltante
Solución: Verifica que tu export siga este patrón:
export const MyComponent = ({ prop }) => (
<div>{prop}</div>
);Error: El build falla mencionando Babel o sintaxis JSX
Causas:
- Sintaxis JSX inválida en tu componente
- Etiquetas o corchetes sin cerrar
- Uso de características de JavaScript no compatibles
Solución: Verifica que tu JSX sea válido. Problemas comunes:
- Todas las etiquetas deben cerrarse (
<img />no<img>) - Usa
classNameen lugar declass - Envuelve múltiples elementos en un fragmento
<>...</>o un elemento padre
Advertencia: Inline component(s) override built-in: Note
Causa: Tu componente en línea tiene el mismo nombre que un componente integrado.
Solución: Renombra tu componente para evitar conflictos:
// Instead of: export const Note = ...
export const CustomNote = ({ children }) => (
<div className="my-note">{children}</div>
);Problema: Las clases de Tailwind no funcionan
Causas:
- Uso de CSS-in-JS u objetos de estilo en línea (soporte limitado)
- La clase de Tailwind no está incluida en el build
Solución: Usa clases de utilidad estándar de Tailwind. Para estilos personalizados, usa la prop style en línea con valores simples:
export const Highlight = ({ children }) => (
<span style={{ backgroundColor: '#ffeb3b' }}>{children}</span>
);Problema: El componente definido con export function no se renderiza
Causa: Solo se admite la sintaxis de función de flecha export const.
Solución: Convierte tu función a sintaxis de función de flecha:
// Instead of:
export function MyComponent({ prop }) {
return <div>{prop}</div>;
}
// Use:
export const MyComponent = ({ prop }) => (
<div>{prop}</div>
);Problema: El componente con guiones bajos o caracteres especiales no funciona
Causa: Los nombres de los componentes deben ser identificadores PascalCase válidos (solo letras y números).
Solución: Usa solo letras y números en el nombre de tu componente:
// Instead of: export const Hero_Card = ...
// Instead of: export const my-component = ...
export const HeroCard = ({ title }) => (
<div>{title}</div>
);Error: ReferenceError: useState is not defined
Causa: Los hooks de React no están disponibles en los componentes en línea. Los componentes en línea se renderizan en el servidor durante el proceso de build, y los hooks solo funcionan en componentes React del lado del cliente.
Solución: Para componentes interactivos que necesiten estado o efectos, crea un archivo de snippet en su lugar:
- Crea un archivo en tu directorio
/snippets(p. ej.,/snippets/counter.tsx) - Agrega
'use client'al principio del archivo - Impórtalo y úsalo en tu MDX
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}
<Counter />