You are currently viewing React Markdown : tout savoir pour afficher du contenu

React Markdown : tout savoir pour afficher du contenu

Dans cet article

  • La bibliothèque react-markdown cumule plus de 13 millions de téléchargements mensuels sur npm en 2026
  • Elle convertit du Markdown en composants React sans recourir à dangerouslySetInnerHTML, ce qui renforce la sécurité
  • Les plugins remark et rehype permettent d’étendre les fonctionnalités : tableaux, coloration syntaxique, maths LaTeX
  • L’intégration d’un éditeur Markdown en temps réel se fait en moins de 50 lignes de code
  • Des alternatives comme markdown-to-jsx ou MDX répondent à des besoins spécifiques selon la taille du projet
  • La protection contre les failles XSS est native grâce au moteur de rendu basé sur un AST

En tant que formatrice BTS SIO et développeuse web, je constate chaque jour que le Markdown s’est imposé comme le format de rédaction universel dans l’écosystème technique. Documentation d’API, articles de blog, fichiers README sur GitHub, commentaires de pull requests : le Markdown est partout. Pourtant, quand il s’agit de l’afficher proprement dans une application React, beaucoup de développeurs hésitent sur la marche à suivre. C’est exactement le problème que résout react markdown.

Dans ce guide complet, je vous accompagne pas à pas pour maîtriser l’affichage de contenu Markdown dans vos projets React. De l’installation à la personnalisation avancée, en passant par la sécurité et les performances, vous aurez toutes les clés pour intégrer cette bibliothèque efficacement.

Pourquoi utiliser react-markdown dans vos projets

Avant de plonger dans le code, je tiens à expliquer pourquoi react-markdown s’est imposée comme la référence. La bibliothèque, maintenue par l’équipe unified/remark sur GitHub, adopte une approche fondamentalement différente des autres solutions : elle ne convertit jamais le Markdown en HTML brut injecté via dangerouslySetInnerHTML. À la place, elle construit un arbre syntaxique abstrait (AST) qu’elle transforme directement en composants React.

Cette architecture apporte trois avantages majeurs :

  • Sécurité native : pas d’injection HTML, donc pas de faille XSS par défaut
  • Contrôle total : chaque élément Markdown peut être remplacé par votre propre composant React
  • Écosystème riche : des dizaines de plugins remark et rehype pour étendre la syntaxe

Avec plus de 13 millions de téléchargements mensuels sur npm, react-markdown est de loin la solution la plus adoptée. Je la recommande systématiquement à mes étudiants en BTS SIO option SLAM, car elle respecte les bonnes pratiques de développement tout en restant accessible aux débutants.

Éditeur Markdown avec prévisualisation en temps réel dans un environnement de développement
Éditeur Markdown avec prévisualisation en temps réel dans un environnement de développement

Installation et configuration de react-markdown

L’installation est simple. Dans un projet React existant (créé avec Vite ou Create React App), ouvrez votre terminal et lancez la commande suivante :

npm install react-markdown

Si vous utilisez yarn ou pnpm :

yarn add react-markdown
# ou
pnpm add react-markdown

La version actuelle (9.x) nécessite React 18 ou supérieur et fonctionne uniquement en ESM (ECMAScript Modules). Voici un premier exemple minimal :

import Markdown from 'react-markdown';

function App() {
  const contenu = `
# Mon premier titre

Ceci est un paragraphe avec du **gras** et de l'*italique*.

- Élément de liste 1
- Élément de liste 2
  `;

  return (
    <div className="article">
      <Markdown>{contenu}</Markdown>
    </div>
  );
}

Ce code suffit pour afficher du contenu Markdown formaté. Le composant <Markdown> accepte une chaîne de caractères en tant qu’enfant (children) et produit les éléments HTML correspondants sous forme de composants React. Je conseille à mes étudiants de commencer par cet exemple avant d’ajouter des fonctionnalités.

Pour les projets en TypeScript, les types sont inclus directement dans le paquet : aucune installation supplémentaire n’est requise. La prop children est typée comme string, ce qui facilite l’intégration avec vos interfaces existantes.

Syntaxe Markdown et rendu de base dans React

React-markdown prend en charge la syntaxe CommonMark complète par défaut. Voici les éléments que vous pouvez utiliser sans aucun plugin supplémentaire :

const exempleComplet = `
# Titre H1
## Titre H2
### Titre H3

Paragraphe avec **gras**, *italique* et ~~barré~~.

[Lien vers web-sio.fr](https://web-sio.fr)

![Alt de l'image](https://exemple.com/photo.jpg)

> Citation en bloc

- Liste non ordonnée
- Deuxième élément

1. Liste ordonnée
2. Deuxième point

\`code en ligne\`

\`\`\`javascript
const x = 42;
console.log(x);
\`\`\`

---

Ligne de séparation ci-dessus
`;

Chaque élément Markdown est converti en son équivalent HTML sémantique : # devient <h1>, **texte** devient <strong>, les listes produisent des <ul> ou <ol> natifs. Cette conversion respecte les standards d’accessibilité, ce qui est un point important pour tout développement web sur mesure.

Un point que je souligne souvent en formation : react-markdown gère correctement les sauts de ligne et les paragraphes multiples. Deux retours à la ligne consécutifs créent un nouveau paragraphe, tandis qu’un simple retour à la ligne est ignoré (comportement standard CommonMark). Pour forcer un saut de ligne au sein d’un paragraphe, ajoutez deux espaces en fin de ligne ou utilisez la balise <br /> si le plugin rehype-raw est activé.

Plugins remark et rehype : étendre les possibilités

La force de react-markdown réside dans son architecture modulaire. Le pipeline de transformation se décompose en deux étapes : les plugins remark agissent sur l’AST Markdown, tandis que les plugins rehype interviennent sur l’AST HTML résultant. Voici les extensions les plus utiles que j’installe systématiquement.

Afficher des tableaux avec remark-gfm

Par défaut, react-markdown ne supporte pas les tableaux Markdown, les listes de tâches ni les liens automatiques. Le plugin remark-gfm (GitHub Flavored Markdown) ajoute ces fonctionnalités :

npm install remark-gfm
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

const tableau = `
| Bibliothèque | Taille | Sécurité |
|---|---|---|
| react-markdown | 12 kB | XSS safe |
| markdown-to-jsx | 6 kB | XSS safe |
| marked + react | 8 kB | Attention |
`;

function TableauDemo() {
  return (
    <Markdown remarkPlugins={[remarkGfm]}>
      {tableau}
    </Markdown>
  );
}

Le rendu produit un <table> HTML standard que vous pouvez styliser avec votre CSS habituel. C’est la question la plus fréquente que je reçois de mes étudiants : comment afficher un react-markdown table correctement. La réponse tient en une ligne d’import.

Coloration syntaxique du code

Pour les blocs de code, le plugin rehype-highlight ou la combinaison react-syntax-highlighter apporte la coloration syntaxique :

npm install react-syntax-highlighter
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';

const composantsPersonnalises = {
  code({ className, children, ...props }) {
    const match = /language-(\w+)/.exec(className || '');
    return match ? (
      <SyntaxHighlighter style={oneDark} language={match[1]}>
        {String(children).replace(/\n$/, '')}
      </SyntaxHighlighter>
    ) : (
      <code className={className} {...props}>
        {children}
      </code>
    );
  }
};

Cette configuration détecte automatiquement le langage spécifié après les trois backticks et applique le thème de coloration correspondant. Je recommande le thème oneDark pour sa lisibilité, mais des dizaines d’autres sont disponibles.

Développement de composants React personnalisés pour le rendu Markdown
Développement de composants React personnalisés pour le rendu Markdown

Personnaliser les composants de rendu

L’une des fonctionnalités les plus puissantes de react markdown est la possibilité de remplacer n’importe quel élément HTML par votre propre composant React. La prop components accepte un objet où chaque clé correspond à un élément HTML :

import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

const composants = {
  h1: ({ children }) => (
    <h1 className="titre-principal text-3xl font-bold mb-4">
      {children}
    </h1>
  ),
  a: ({ href, children }) => (
    <a
      href={href}
      className="lien-article text-blue-600 underline"
      target={href.startsWith('http') ? '_blank' : undefined}
      rel={href.startsWith('http') ? 'noopener noreferrer' : undefined}
    >
      {children}
    </a>
  ),
  img: ({ src, alt }) => (
    <figure className="my-6">
      <img src={src} alt={alt} loading="lazy" className="rounded-lg" />
      <figcaption className="text-sm text-gray-500 mt-2">{alt}</figcaption>
    </figure>
  ),
  blockquote: ({ children }) => (
    <blockquote className="border-l-4 border-blue-500 pl-4 italic my-4">
      {children}
    </blockquote>
  ),
};

function ArticleMarkdown({ contenu }) {
  return (
    <Markdown
      remarkPlugins={[remarkGfm]}
      components={composants}
    >
      {contenu}
    </Markdown>
  );
}

Cette approche est particulièrement utile quand vous travaillez avec un design system ou un framework CSS comme Tailwind. Plutôt que de lutter avec des sélecteurs CSS globaux, vous mappez directement chaque élément Markdown vers vos composants stylisés. C’est d’ailleurs la même logique de composition que l’on retrouve dans la navigation React, où chaque route correspond à un composant dédié.

Les éléments personnalisables incluent : h1 à h6, p, a, img, blockquote, code, pre, ul, ol, li, table, thead, tbody, tr, th, td, hr, em, strong, et bien d’autres. Chaque composant reçoit les props appropriées (href pour les liens, src pour les images, etc.).

Créer un éditeur Markdown en temps réel avec React

Un cas d’usage fréquent consiste à proposer un react-markdown editor avec prévisualisation en temps réel. L’idée est simple : un champ de saisie à gauche, le rendu à droite. Voici une implémentation complète :

import { useState } from 'react';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

const texteInitial = `# Bienvenue

Écrivez votre **Markdown** ici et voyez le rendu en direct.

## Fonctionnalités
- Gras et italique
- Listes
- [Liens](https://web-sio.fr)

| Col 1 | Col 2 |
|-------|-------|
| A     | B     |
`;

function EditeurMarkdown() {
  const [texte, setTexte] = useState(texteInitial);

  return (
    <div style={{ display: 'flex', gap: '1rem', height: '80vh' }}>
      <textarea
        value={texte}
        onChange={(e) => setTexte(e.target.value)}
        style={{
          flex: 1,
          fontFamily: 'monospace',
          fontSize: '14px',
          padding: '1rem',
          border: '1px solid #ccc',
          borderRadius: '8px',
          resize: 'none'
        }}
      />
      <div
        style={{
          flex: 1,
          padding: '1rem',
          border: '1px solid #ccc',
          borderRadius: '8px',
          overflow: 'auto'
        }}
      >
        <Markdown remarkPlugins={[remarkGfm]}>{texte}</Markdown>
      </div>
    </div>
  );
}

Cet éditeur fonctionne parfaitement pour des cas simples. Pour des besoins plus avancés (barre d’outils, raccourcis clavier, mode plein écran), je recommande d’explorer react-markdown-editor-lite, qui fournit un composant éditeur complet prêt à l’emploi :

npm install react-markdown-editor-lite

Cette bibliothèque offre une barre d’outils configurable, le glisser-déposer d’images, et un mode split-screen natif. Elle s’intègre directement avec react-markdown pour le rendu de la prévisualisation, ce qui garantit une cohérence parfaite entre l’édition et l’affichage final.

Sécurité et performances : les bonnes pratiques

La sécurité informatique est un sujet que je prends très au sérieux, surtout quand il s’agit d’afficher du contenu généré par les utilisateurs. React-markdown excelle sur ce point grâce à son approche basée sur l’AST.

Protection contre les attaques XSS

Contrairement à des solutions qui utilisent innerHTML, react-markdown ne passe jamais par du HTML brut. Le contenu Markdown est parsé en un arbre syntaxique, puis chaque nœud est converti en appel React.createElement(). Cette mécanique rend impossible l’injection de scripts par défaut.

Attention cependant : si vous activez le plugin rehype-raw pour autoriser le HTML dans votre Markdown, vous réintroduisez un risque. Dans ce cas, utilisez impérativement rehype-sanitize pour filtrer les balises dangereuses :

import rehypeRaw from 'rehype-raw';
import rehypeSanitize from 'rehype-sanitize';

<Markdown
  rehypePlugins={[rehypeRaw, rehypeSanitize]}
>
  {contenuUtilisateur}
</Markdown>

Le plugin rehype-sanitize utilise par défaut le schéma de GitHub, qui autorise les balises courantes (<div>, <span>, <details>) tout en bloquant <script>, <iframe>, <style> et les attributs événementiels. Vous pouvez également créer votre propre schéma pour un contrôle plus fin, conformément aux recommandations de la fiche OWASP sur la prévention XSS.

Optimiser les performances de rendu

Pour des documents longs (plus de 5 000 mots), le parsing peut devenir coûteux. Voici mes recommandations :

  • Encapsulez le composant <Markdown> dans React.memo() pour éviter les re-rendus inutiles
  • Utilisez useMemo pour mémoriser le contenu Markdown quand il provient de props ou d’un état parent
  • Pour les contenus très longs, envisagez la virtualisation en découpant le Markdown en sections
  • Chargez les plugins de coloration syntaxique en lazy loading avec React.lazy()
import { useMemo, memo } from 'react';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

const ArticleOptimise = memo(function ArticleOptimise({ source }) {
  const contenu = useMemo(() => source, [source]);

  return (
    <Markdown remarkPlugins={[remarkGfm]}>
      {contenu}
    </Markdown>
  );
});
Documentation technique avec tableaux et blocs de code rendus via react-markdown
Documentation technique avec tableaux et blocs de code rendus via react-markdown

Comparatif des bibliothèques Markdown pour React

React-markdown n’est pas la seule option disponible. Selon votre projet, une alternative pourrait mieux convenir. Voici un comparatif détaillé des principales solutions :

Bibliothèque Taille (gzip) Sécurité XSS Plugins Composants custom Cas d’usage idéal
react-markdown ~12 kB Native (AST) remark + rehype Oui, complet Projets standards, documentation
markdown-to-jsx ~6 kB Native Limités Oui Projets légers, bundles réduits
MDX ~30 kB Dépend config remark + rehype JSX natif Documentation interactive, blogs
marked + react ~8 kB Nécessite sanitize Extensions marked Non natif Migration depuis marked
remark-react ~10 kB Native remark Oui Pipelines unified existants

Mon conseil : si vous démarrez un nouveau projet, partez sur react-markdown. Sa communauté est la plus active, sa documentation est excellente et son écosystème de plugins couvre 99 % des besoins. Pour les projets où chaque kilooctet compte (applications mobiles avec React Native Web par exemple), markdown-to-jsx est une alternative solide à moitié moins lourde.

Si votre besoin est d’intégrer des composants React directement dans le contenu Markdown (un graphique interactif dans un article, un formulaire dans une documentation), alors MDX est la solution appropriée. MDX permet d’écrire du JSX au sein même du fichier Markdown, ce qui ouvre des possibilités infinies mais ajoute de la complexité au build.

Cas pratiques avancés et intégrations courantes

Pour conclure la partie technique, je partage ici trois cas que je rencontre régulièrement en tant que développeuse et formatrice.

Charger du Markdown depuis un fichier ou une API

Dans un projet réel, le contenu Markdown provient rarement d’une constante. Voici comment le charger dynamiquement depuis un fichier local ou une API :

import { useState, useEffect } from 'react';
import Markdown from 'react-markdown';

function ArticleDepuisAPI({ articleId }) {
  const [contenu, setContenu] = useState('');
  const [chargement, setChargement] = useState(true);

  useEffect(() => {
    fetch(`/api/articles/${articleId}`)
      .then(res => res.text())
      .then(texte => {
        setContenu(texte);
        setChargement(false);
      });
  }, [articleId]);

  if (chargement) return <p>Chargement...</p>;

  return <Markdown>{contenu}</Markdown>;
}

Avec Vite, vous pouvez également importer un fichier .md comme une chaîne brute grâce au suffixe ?raw :

import contenuArticle from './article.md?raw';
import Markdown from 'react-markdown';

function Page() {
  return <Markdown>{contenuArticle}</Markdown>;
}

Gérer les images avec lazy loading

Pour les articles riches en images, la personnalisation du composant img permet d’ajouter le chargement différé et un style responsive :

const composants = {
  img: ({ src, alt }) => (
    <img
      src={src}
      alt={alt}
      loading="lazy"
      decoding="async"
      style={{ maxWidth: '100%', height: 'auto', borderRadius: '8px' }}
    />
  )
};

Intégration avec un CMS headless

Si vous utilisez un CMS headless comme Strapi ou Contentful, le contenu est souvent stocké en Markdown. React-markdown s’intègre naturellement dans ce workflow : vous récupérez le champ Markdown via l’API du CMS, puis vous le passez au composant. C’est le react markdown example le plus courant en production. Pour les projets plus complexes impliquant de la 3D avec React Three Fiber ou des visualisations interactives, vous pouvez combiner react-markdown avec MDX pour incorporer des composants dynamiques directement dans votre contenu éditorial.

Je recommande également de consulter la spécification officielle CommonMark pour maîtriser les subtilités de la syntaxe, surtout quand vous devez documenter des projets complexes comme ceux que l’on aborde en poursuite d’études après le BTS SIO.

Côté gestion des versions, react-markdown suit le versioning sémantique. La migration de la version 8 vers la version 9 a introduit le passage au format ESM pur, ce qui peut nécessiter des ajustements dans votre configuration de bundler. Vérifiez la compatibilité avec votre outil de build avant de mettre à jour.

Pour celles et ceux qui souhaitent protéger le contenu affiché et respecter la réglementation, je rappelle que le RGPD impose des obligations aux développeurs, notamment concernant les données personnelles qui pourraient apparaître dans du contenu Markdown généré par les utilisateurs.

À retenir

  • Installez react-markdown et remark-gfm comme base pour couvrir la majorité des besoins Markdown dans React
  • Utilisez la prop components pour mapper chaque élément Markdown vers vos composants React personnalisés
  • Ne jamais activer rehype-raw sans rehype-sanitize quand le contenu provient d’utilisateurs externes
  • Optimisez les performances avec React.memo et useMemo pour les documents longs ou les rendus fréquents
  • Préférez markdown-to-jsx si la taille du bundle est critique, et MDX si vous avez besoin de composants interactifs dans le contenu

Questions fréquentes


Comment fonctionne react-markdown en interne ?

React-markdown utilise le parser unified pour transformer le texte Markdown en un arbre syntaxique abstrait (AST). Cet AST est ensuite converti en éléments React via React.createElement(), sans jamais passer par du HTML brut. Cette approche garantit la sécurité contre les injections XSS et permet de remplacer n’importe quel élément par un composant React personnalisé grâce à la prop components.

Comment afficher un tableau Markdown dans React ?

Par défaut, react-markdown ne supporte pas les tableaux. Il faut installer le plugin remark-gfm (GitHub Flavored Markdown) avec la commande npm install remark-gfm, puis le passer dans la prop remarkPlugins du composant. Le tableau sera alors rendu sous forme de balises HTML table, thead, tbody, tr, th et td que vous pouvez styliser librement.

Quelle est la différence entre react-markdown et MDX ?

React-markdown est une bibliothèque de rendu qui prend une chaîne Markdown et la convertit en composants React à l’exécution. MDX est un format de fichier qui permet d’écrire du JSX directement dans le Markdown, mais nécessite une étape de compilation (build-time). MDX est plus puissant pour la documentation interactive, tandis que react-markdown est plus simple pour afficher du contenu dynamique provenant d’une API ou d’une base de données.

React-markdown est-il sécurisé contre les attaques XSS ?

Oui, par défaut react-markdown est sécurisé contre les attaques XSS car il ne convertit jamais le Markdown en HTML brut injecté via dangerouslySetInnerHTML. Le contenu passe par un arbre syntaxique et est rendu via React.createElement(). Cependant, si vous activez le plugin rehype-raw pour autoriser le HTML brut dans le Markdown, vous devez impérativement ajouter rehype-sanitize pour filtrer les balises dangereuses.

Comment créer un éditeur Markdown avec prévisualisation en React ?

La méthode la plus simple consiste à utiliser un composant textarea contrôlé par un état React (useState), et à passer la valeur de cet état au composant react-markdown pour la prévisualisation. Pour un éditeur plus complet avec barre d’outils et raccourcis clavier, la bibliothèque react-markdown-editor-lite fournit un composant prêt à l’emploi qui s’intègre directement avec react-markdown.

Peut-on utiliser react-markdown avec TypeScript ?

Oui, react-markdown inclut ses propres définitions de types TypeScript depuis la version 8. Aucun paquet @types supplémentaire n’est nécessaire. Les props du composant sont correctement typées, notamment children (string), remarkPlugins, rehypePlugins et components. Les composants personnalisés passés via la prop components bénéficient également d’un typage précis pour les props de chaque élément HTML.


Lucie Moreau
Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.

Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.