ToolPal
Code sur un moniteur sombre montrant la syntaxe React JSX

HTML vers JSX : Les 7 pieges qui font trebucher tout debutant React

📷 Pexels / Pexels

HTML vers JSX : Les 7 pieges qui font trebucher tout debutant React

className, htmlFor, balises auto-fermantes, styles en ligne - la conversion HTML vers JSX est pleine de pieges subtils. Apprenez-les une fois et ne les deboguez plus jamais.

DPar Daniel Park28 mars 202612 min de lecture

Il y a un rite de passage qui arrive a presque chaque developpeur apprenant React. Vous avez un beau morceau de HTML - peut-etre d'un transfert de design, d'un modele statique ou de quelque chose que vous avez copie d'un ancien projet - et vous le deposez directement dans un composant. Puis les erreurs commencent.

Warning: Invalid DOM property `class`. Did you mean `className`?

Puis une autre.

Warning: Invalid DOM property `for`. Did you mean `htmlFor`?

Puis peut-etre une erreur d'analyse d'une balise <img> ou <input> non fermee. Au moment ou vous avez fait defiler six avertissements, vous vous demandez pourquoi React ne pouvait pas simplement accepter du HTML normal. Question valable, en fait.

Pourquoi JSX n'est pas juste du HTML

La reponse courte : JSX ressemble a du HTML mais c'est du JavaScript deguise. Quand Babel traite votre composant, chaque <div className="wrapper"> devient React.createElement('div', { className: 'wrapper' }). Cette transformation est ce qui rend JSX si puissant - mais c'est aussi pourquoi vous ne pouvez pas copier du HTML mot pour mot.

HTML est un langage de balisage. Il a ses propres regles d'analyse, et les navigateurs sont concus pour etre indulgents a son egard. JSX est une syntaxe JavaScript qui ressemble par hasard a du HTML. Les parseurs JavaScript ne sont pas indulgents. Ils ont des mots-cles reserves, des regles de syntaxe strictes et aucune tolerance pour l'ambiguite.

Cette tension - la souplesse de HTML contre la rigueur de JavaScript - est la cause profonde de chaque erreur de conversion que vous rencontrerez.

Les transformations que vous devez connaitre

1. classclassName

C'est ce que tout le monde apprend en premier, generalement par un avertissement.

<!-- HTML -->
<div class="container main-content">
  <p class="text-gray">Hello world</p>
</div>
// JSX
<div className="container main-content">
  <p className="text-gray">Hello world</p>
</div>

La raison est simple : class est un mot-cle reserve en JavaScript (c'est ainsi que vous definissez les classes ES6). Si JSX permettait class comme attribut, le parseur JavaScript serait confus. className est une solution de contournement mince qui correspond directement a la propriete DOM du meme nom - quand React rend sur le vrai DOM, il definit la propriete className, ce qui correspond a l'attribut HTML class. Le resultat final est identique ; seule la syntaxe change.

2. forhtmlFor

Meme logique. for est un mot-cle reserve en JavaScript (c'est ainsi que vous ecrivez des boucles for). Les etiquettes dans les formulaires utilisent for pour se connecter a l'id d'une entree :

<!-- HTML -->
<label for="email">Email address</label>
<input type="email" id="email" />
// JSX
<label htmlFor="email">Email address</label>
<input type="email" id="email" />

Beaucoup de developpeurs se souviennent de className mais oublient htmlFor. Moins souvent discute mais lancera le meme type d'avertissement si vous le manquez.

3. Elements vides auto-fermes

En HTML, les elements vides - les balises qui ne peuvent pas avoir d'enfants - n'ont pas besoin d'un slash de fermeture. Les navigateurs s'en accommodent :

<!-- Valid HTML -->
<img src="photo.jpg" alt="A photo">
<input type="text" name="username">
<br>
<hr>
<meta charset="UTF-8">

JSX exige que chaque element soit explicitement ferme. Soit vous ajoutez le slash de fermeture avant le >, soit vous ajoutez une balise de fermeture separee :

// JSX - doit se fermer automatiquement
<img src="photo.jpg" alt="A photo" />
<input type="text" name="username" />
<br />
<hr />
<meta charSet="UTF-8" />

Notez que j'ai aussi change charset en charSet dans ce dernier exemple. C'est le schema camelCase, dont nous parlerons ensuite.

4. Attributs camelCase

Les attributs HTML sont insensibles a la casse. Les noms d'attributs JSX correspondent aux proprietes DOM, et les proprietes DOM suivent les conventions camelCase. Les plus courants que vous rencontrerez :

HTMLJSX
onclickonClick
onchangeonChange
tabindextabIndex
maxlengthmaxLength
readonlyreadOnly
autocompleteautoComplete
autofocusautoFocus
crossorigincrossOrigin
charsetcharSet

Les gestionnaires d'evenements sont probablement les plus frequemment rencontres. Les attributs d'evenements HTML utilisent tout en minuscules :

<!-- HTML -->
<button onclick="handleClick()">Click me</button>
<input onchange="handleChange(event)" />

En JSX, ils sont camelCase et vous passez une reference de fonction (pas une chaine) :

// JSX
<button onClick={handleClick}>Click me</button>
<input onChange={handleChange} />

Ce dernier point - passer une reference de fonction plutot qu'un appel de chaine - est une difference importante. En HTML onclick, la valeur est une chaine de JavaScript a executer. En JSX onClick, la valeur est une expression JavaScript (generalement une reference de fonction). C'est pourquoi JSX utilise des accolades {} autour de la valeur plutot que des guillemets.

5. Styles en ligne en tant qu'objets JavaScript

Cela surprend les gens la premiere fois. Les styles en ligne HTML sont des chaines :

<!-- HTML -->
<div style="color: red; font-size: 16px; margin-top: 8px;">
  Styled text
</div>

Les styles en ligne JSX sont des objets JavaScript, ce qui signifie :

  • Doubles accolades (une paire pour l'expression JSX, une pour le litteral d'objet)
  • Noms de proprietes en camelCase
  • Valeurs sous forme de chaines ou de nombres (les nombres pour les valeurs de pixels peuvent optionnellement etre des nombres simples)
// JSX
<div style={{ color: 'red', fontSize: '16px', marginTop: '8px' }}>
  Styled text
</div>

La regle camelCase s'applique ici aussi : font-size devient fontSize, margin-top devient marginTop, background-color devient backgroundColor. Toute propriete CSS avec un tiret devient camelCase.

6. Commentaires

En HTML, vous ecrivez <!-- comment -->. En JSX, les commentaires de style HTML ne fonctionnent pas. Vous devez utiliser des commentaires JavaScript dans une expression JSX :

<!-- HTML comment -->
<div>
  <!-- This is a comment -->
  <p>Content</p>
</div>
{/* JSX comment */}
<div>
  {/* This is a comment */}
  <p>Content</p>
</div>

Vous pouvez egalement utiliser // pour les commentaires sur une seule ligne, mais uniquement dans les accolades ou dans le code JavaScript normal - pas directement dans le balisage JSX.

Les pieges moins evidents

Les attributs booleens se comportent differemment

En HTML, la presence d'un attribut implique true pour les attributs booleens :

<!-- HTML - ces options sont equivalentes -->
<input disabled>
<input disabled="true">
<input disabled="disabled">

En JSX, les attributs booleens peuvent etre ecrits en forme courte (comme HTML), mais la forme explicite est differente :

// JSX - ceux-ci sont tous equivalents
<input disabled />
<input disabled={true} />

Ce que vous devriez eviter en JSX, c'est disabled="true" (avec guillemets), car cela passe la chaine "true" plutot que le booleen true. React pourrait le rendre correctement, mais ce n'est pas idiomatique et peut causer des problemes avec certains composants.

La prop key dans les listes

Quand vous convertissez des listes HTML en JSX et que vous mappez des donnees, React a besoin d'une prop key sur chaque element. Ce n'est pas un probleme de conversion HTML vers JSX en soi - il s'applique uniquement lorsque vous generez des elements dynamiquement - mais c'est bon a savoir avant d'obtenir l'avertissement :

// React avertira sans key
{items.map((item) => (
  <li key={item.id}>{item.name}</li>
))}

Attributs SVG

SVG a son propre ensemble de bizarreries de denomination d'attributs. En HTML/SVG, vous pourriez ecrire fill-opacity, stroke-width, clip-path. En JSX, ils deviennent fillOpacity, strokeWidth, clipPath. Si vous collez du SVG en ligne depuis une bibliotheque d'icones ou un outil de design, attendez-vous a faire un peu de nettoyage.

tabindex vs tabIndex

Facile a manquer. Si vous construisez des composants accessibles et definissez tabindex manuellement, rappelez-vous que cela devient tabIndex en JSX. Manquer cela ne generera pas toujours une erreur - React peut quand meme le rendre - mais c'est une difference silencieuse qui pourrait affecter le comportement.

Quand utiliser un convertisseur automatique

Si vous avez un grand bloc de HTML - un composant d'un systeme de design, un modele que vous migrez depuis une base de code non-React, ou un extrait d'une source en ligne - utiliser un convertisseur est le choix pratique. Remplacer manuellement chaque class par className et chaque gestionnaire d'evenements avec tiret est fastidieux et sujet aux erreurs.

Le convertisseur ToolPal HTML vers JSX gere les transformations standard automatiquement : classclassName, forhtmlFor, chaines de styles → objets de styles, elements vides auto-fermes, attributs camelCase. Vous collez votre HTML, obtenez du JSX valide en retour, et continuez.

La ou les convertisseurs automatiques ne peuvent pas aider, ce sont les decisions structurelles. Convertir 500 lignes de HTML en une seule instruction de retour JSX ne vous donne pas un composant bien architecture - cela vous donne un blob converti. Pour tout ce qui est substantiel, le convertisseur gere la syntaxe mais vous devez toujours decider comment diviser le resultat en composants plus petits, ou les props devraient remplacer les valeurs codees en dur, et quelles parties devraient etre dynamiques.

Utilisez le convertisseur pour la transformation mecanique. Utilisez votre cerveau pour l'architecture.

Quand ecrire JSX de zero

Si vous construisez un nouveau composant et que vous avez le design en tete (ou dans une maquette), ecrire directement du JSX est souvent plus rapide que d'ecrire du HTML et de le convertir. Vous ecrirez className des le debut, vous n'oublierez pas de fermer vos elements vides, et vous ne vous retrouverez pas avec des chaines de styles qui ont besoin d'etre converties.

Les cas ou la conversion aide vraiment :

Migration depuis un projet non-React. Si vous avez des modeles HTML existants - d'un site HTML/CSS simple, d'une application Rails ou d'un modele Jinja - les outils de conversion font gagner un temps reel.

Travail a partir d'un transfert de design. Les designers exportent souvent du balisage HTML ou fournissent des extraits. Les passer dans un convertisseur est plus rapide que de les retaper.

Coller des extraits tiers. Les exemples de code provenant de documentation, de reponses Stack Overflow ou de tutoriels sont souvent ecrits en HTML. Une conversion rapide vous donne du JSX utilisable sans edition manuelle.

Grands formulaires. Les formulaires avec des dizaines d'entrees, d'etiquettes et de fieldsets sont fastidieux a ecrire a la main. Collez la structure HTML, convertissez-la, puis remplacez les valeurs codees en dur par des props et un etat.

Un exemple de conversion realiste

Voici un petit composant de carte en HTML :

<div class="card" id="product-card">
  <img src="/product.jpg" alt="Product photo" class="card-image">
  <div class="card-body">
    <h2 class="card-title">Product Name</h2>
    <p class="card-description" style="color: #666; font-size: 14px;">
      A short description of the product.
    </p>
    <label for="quantity">Quantity</label>
    <input type="number" id="quantity" min="1" max="99" readonly>
    <button class="btn btn-primary" onclick="addToCart()">Add to Cart</button>
  </div>
</div>

Apres conversion :

<div className="card" id="product-card">
  <img src="/product.jpg" alt="Product photo" className="card-image" />
  <div className="card-body">
    <h2 className="card-title">Product Name</h2>
    <p className="card-description" style={{ color: '#666', fontSize: '14px' }}>
      A short description of the product.
    </p>
    <label htmlFor="quantity">Quantity</label>
    <input type="number" id="quantity" min="1" max="99" readOnly />
    <button className="btn btn-primary" onClick={addToCart}>Add to Cart</button>
  </div>
</div>

Notez chaque changement :

  • Tous les classclassName
  • <img> et <input> sont auto-fermes avec />
  • La chaine style → objet de style avec des proprietes camelCase
  • forhtmlFor
  • readonlyreadOnly
  • onclick="addToCart()"onClick={addToCart} (reference de fonction, sans parentheses)

Ce dernier point sur le gestionnaire d'evenements vaut la peine d'etre souligne. Dans la version HTML, onclick="addToCart()" est une chaine qui est evaluee. Si vous ecrivez accidentellement onClick="addToCart()" en JSX, React lancera une erreur disant que les gestionnaires d'evenements doivent etre des fonctions, pas des chaines. Et si vous ecrivez onClick={addToCart()} (avec des parentheses), vous appellerez la fonction immediatement au rendu plutot qu'au clic. Ce sont deux erreurs courantes de debutants.

Quelques choses que les convertisseurs ne peuvent pas gerer

Contenu dynamique. Un convertisseur ne sait pas que Product Name devrait devenir {product.name}. Il convertira la structure mais vous devrez remplacer les valeurs statiques par des props et un etat vous-meme.

Logique du gestionnaire d'evenements. onclick="addToCart()" se convertira en onClick={addToCart}, mais addToCart doit toujours etre defini quelque part dans votre composant. Le convertisseur vous donne la syntaxe d'attribut ; la fonction est votre responsabilite.

Rendu conditionnel. HTML n'a pas de concept de "afficher cet element seulement si X est vrai". Ce schema est quelque chose que vous ajoutez lors de l'etape de composantisation, pas quelque chose qu'un convertisseur peut deduire d'un balisage statique.

Plusieurs elements racine. Si votre extrait HTML a deux elements freres au niveau superieur, le JSX converti aura egalement deux elements freres - ce qui est invalide dans une instruction de retour de composant. Vous devrez les envelopper dans un <div> ou un fragment <>...</>.


La conversion HTML vers JSX est l'une de ces choses qui semble ennuyeuse jusqu'a ce qu'elle devienne une seconde nature. Apres quelques semaines d'ecriture de React, vous taperez automatiquement className sans y penser. Vous fermerez vos balises <img /> reflexivement. Mais jusqu'a ce que cette memoire musculaire se developpe, des outils comme le convertisseur ToolPal HTML vers JSX rendent la transition plus rapide et moins frustrante.

La vraie competence n'est pas de memoriser les differences de syntaxe - c'est de comprendre pourquoi elles existent. Une fois que vous comprenez que JSX est du JavaScript, les regles cessent de sembler arbitraires et commencent a avoir du sens.

Questions Fréquentes

D

À propos de l'auteur

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

En savoir plus

Partager

XLinkedIn

Articles associés