Componenti React personalizzati
Definisci e usa componenti React personalizzati nei file MDX con rendering lato server, stili Tailwind e accesso ai componenti Jamdesk integrati.
Definisci componenti React personalizzati direttamente nei file MDX. Esporta un componente arrow function nella parte iniziale del file e usalo inline. I componenti vengono renderizzati lato server durante la build, con accesso a tutti i componenti integrati di Jamdesk e alle classi Tailwind.
Utilizzo di base
Definisci un componente usando la sintassi export const nella parte iniziale del file 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.
I nomi dei componenti devono usare il PascalCase (iniziare con una lettera maiuscola).
Esempio: scheda hero
Ecco un esempio più complesso con più props e classi 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>
Utilizzo dei componenti integrati
I tuoi componenti personalizzati hanno accesso a tutti i componenti integrati di Jamdesk. Non sono necessari import:
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>
Componenti integrati per categoria:
| Categoria | Componenti |
|---|---|
| Callout | Note, Tip, Info, Warning, Check, Danger |
| Layout | Card, Columns, Tabs, Tab, Accordion, Steps, Step, View |
| Media | Frame, Icon, Badge, Tooltip |
| Codice | CodeGroup |
| Documentazione API | ParamField, ResponseField, Expandable |
Limitazioni
- Solo arrow function: usa la sintassi
export const. La sintassiexport functionnon è supportata. - Nessun import: non puoi importare pacchetti esterni o altri file.
- Nessun hook: gli hook React (
useState,useEffect,useRef, ecc.) non sono disponibili. I componenti vengono renderizzati lato server durante la build e gli hook funzionano solo lato client. Per i componenti interattivi, usa invece i file snippet (vedi la sezione sulla risoluzione dei problemi). - Solo lato server: i componenti vengono renderizzati sul server; non sono disponibili interattività lato client o gestori di eventi.
- Solo Tailwind: usa le classi CSS Tailwind per gli stili; CSS-in-JS non è disponibile.
- Sintassi rigorosa: gli errori di sintassi nei componenti inline interrompono la build con un messaggio di errore chiaro.
- Nomi in PascalCase: i nomi dei componenti devono iniziare con una lettera maiuscola e contenere solo lettere e numeri (nessun carattere di sottolineatura).
Servono gli hook React? I componenti inline non possono usare useState, useEffect o altri hook perché vengono renderizzati sul server durante la build. Per i componenti interattivi che richiedono stato o effetti, crea un file snippet con la direttiva 'use client' (vedi la sezione sulla risoluzione dei problemi qui sotto).
Best practice
I componenti inline dovrebbero essere presentazionali. Per la logica complessa, richiedi un componente integrato.
Assicurati che i tuoi componenti siano accessibili, usando elementi HTML e attributi ARIA appropriati.
Visualizza in anteprima la documentazione localmente per verificare che i componenti vengano renderizzati correttamente sia in modalità chiara sia in modalità scura.
Risoluzione dei problemi
Errore: Expected component 'MyComponent' to be defined
Cause:
- Il nome del componente non usa il PascalCase (deve iniziare con una lettera maiuscola)
- Errore di sintassi nella definizione del componente
- Tag di chiusura o parentesi mancanti
Soluzione: verifica che l'export segua questo schema:
export const MyComponent = ({ prop }) => (
<div>{prop}</div>
);Errore: la build non riesce e segnala Babel o la sintassi JSX.
Cause:
- Sintassi JSX non valida nel componente
- Tag o parentesi non chiusi
- Utilizzo di funzionalità JavaScript non supportate
Soluzione: verifica che il tuo JSX sia valido. Problemi comuni:
- Tutti i tag devono essere chiusi (
<img loading="lazy" />, non<img loading="lazy">) - Usa
classNameinvece diclass - Racchiudi più elementi in un fragment
<>...</>o in un elemento padre
Avviso: Inline component(s) override built-in: Note
Causa: il tuo componente inline ha lo stesso nome di un componente integrato.
Soluzione: rinomina il componente per evitare conflitti:
// Instead of: export const Note = ...
export const CustomNote = ({ children }) => (
<div className="my-note">{children}</div>
);Problema: le classi Tailwind non funzionano.
Cause:
- Utilizzo di CSS-in-JS o oggetti di stile inline (supporto limitato)
- La classe Tailwind non è inclusa nella build
Soluzione: usa le classi utility Tailwind standard. Per gli stili personalizzati, usa la prop style inline con valori semplici:
export const Highlight = ({ children }) => (
<span style={{ backgroundColor: '#ffeb3b' }}>{children}</span>
);Problema: il componente definito con export function non viene renderizzato.
Causa: è supportata solo la sintassi arrow function con export const.
Soluzione: converti la funzione nella sintassi arrow function:
// Instead of:
export function MyComponent({ prop }) {
return <div>{prop}</div>;
}
// Use:
export const MyComponent = ({ prop }) => (
<div>{prop}</div>
);Problema: un componente con caratteri di sottolineatura o caratteri speciali non funziona.
Causa: i nomi dei componenti devono essere identificatori PascalCase validi (solo lettere e numeri).
Soluzione: usa solo lettere e numeri nel nome del componente:
// Instead of: export const Hero_Card = ...
// Instead of: export const my-component = ...
export const HeroCard = ({ title }) => (
<div>{title}</div>
);Errore: ReferenceError: useState is not defined
Causa: gli hook React non sono disponibili nei componenti inline. I componenti inline vengono renderizzati lato server durante il processo di build e gli hook funzionano solo nei componenti React lato client.
Soluzione: per i componenti interattivi che richiedono stato o effetti, crea invece un file snippet:
- Crea un file nella directory
/snippets(ad esempio/snippets/counter.tsx) - Aggiungi
'use client'nella parte iniziale del file - Importalo e usalo nel tuo 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>
);
}import { Counter } from '/snippets/counter';
<Counter />