Passer au contenu principal
Les composants React sont un moyen puissant de créer des éléments interactifs et réutilisables dans votre documentation.

Utiliser des composants React

Vous pouvez créer des composants React directement dans vos fichiers MDX à l’aide des hooks React.

Exemple

Cet exemple déclare un composant Counter, puis l’utilise avec <Counter />.
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="Diminuer"
        >
          -
        </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="Augmenter"
        >
          +
        </button>
      </div>
    </div>
  )
}

<Counter />
Le compteur est rendu sous la forme d’un composant React interactif.

Importation de composants

Pour importer des composants React dans vos fichiers MDX, les fichiers des composants doivent être placés dans le dossier snippets. Vous pouvez ensuite les importer dans n’importe quelle page MDX de votre documentation. En savoir plus sur les extraits réutilisables.

Exemple

Cet exemple déclare un composant ColorGenerator qui utilise plusieurs hooks React, puis l’emploie dans un fichier MDX. Créez le fichier color-generator.jsx dans le dossier snippets :
/snippets/color-generator.jsx
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(`${color} copié dans le presse-papiers !`)
      })
      .catch((err) => {
        console.error("Échec de la copie : ", 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">
            Teinte : {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">
            Luminosité : {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={`Cliquer pour copier : ${color}`}
              onClick={() => copyToClipboard(color)}
            />
          ))}
        </div>

        <div className="text-sm font-mono text-zinc-950/70 dark:text-white/70">
          <p>
            Couleur de base : hsl({hue}, {saturation}%, {lightness}%)
          </p>
        </div>
      </div>
    </div>
  )
}
Importez le composant ColorGenerator et utilisez-le dans un fichier MDX :
import { ColorGenerator } from "/snippets/color-generator.jsx"

<ColorGenerator />
Le générateur de couleurs se présente sous la forme d’un composant React interactif.

Considérations

Les composants à hooks React s’exécutent côté client, ce qui a plusieurs implications :
  • SEO : Les moteurs de recherche peuvent ne pas indexer entièrement le contenu dynamique.
  • Chargement initial : Les visiteurs peuvent voir un flash de chargement avant que les composants ne s’affichent.
  • Accessibilité : Assurez-vous que les modifications de contenu dynamique sont annoncées aux lecteurs d’écran.
  • Optimiser les tableaux de dépendances : N’incluez que les dépendances nécessaires dans vos tableaux de dépendances useEffect.
  • Mémoriser les calculs complexes : Utilisez useMemo ou useCallback pour les opérations coûteuses.
  • Réduire les re-rendus : Scindez les gros composants en composants plus petits pour éviter les re-rendus en cascade.
  • Chargement différé : Envisagez le chargement différé des composants complexes pour améliorer le temps de chargement initial de la page.