Lorsque l’on débute avec React ou Next.js, on entend très vite parler de JSX — cette syntaxe “HTML-like” qui semble familière… jusqu’à ce qu’elle ne le soit plus.
Pourquoi class devient className ? Pourquoi les if ne fonctionnent pas dans un return ? Et pourquoi faut-il écrire htmlFor au lieu de for ?
Autant de petites différences qui, cumulées, peuvent vite semer le doute chez les apprenants — ou casser un composant pour une raison invisible à l’œil non averti.
Dans cette fiche synthèse, je te propose un tour d’horizon des 10 différences clés à connaître pour bien écrire du JSX, comprendre les erreurs les plus fréquentes, et structurer ton code React avec clarté et confiance.
1. Ce qu’est JSX
JSX (JavaScript XML) est une extension de syntaxe pour JavaScript qui permet d’écrire du HTML dans du JavaScript. En réalité, ce n’est pas du HTML, mais une représentation déclarative de l’UI.
JSX est transpilé (généralement par Babel) en appels JavaScript classiques comme React.createElement().
Comment React fonctionne en coulisse
React.createElement() est bien utilisé en interne, même avec Next.js, mais tu ne le vois jamais. Next.js intègre déjà Babel et les transformations JSX, donc tu n’as jamais besoin d’écrire ou voir React.createElement() à la main.
Quand tu écris ce composant :
export default function Hello() {
return <h1>Hello, React !</h1>;
}
Next.js passe le JSX dans Babel. Babel convertit çà en React.createElement(…). React utilise ensuite ces React Elements pour construire le Virtual DOM et React affiche le bon contenu dans le navigateur. Le Virtual DOM (ou DOM virtuel) est une copie légère de la page web que React utilise pour travailler plus vite et plus proprement.
JSX n’est pas juste une syntaxe agréable — il joue un rôle central dans la façon dont React pense et construit l’interface utilisateur.
Lisibilité
JSX ressemble beaucoup à du HTML, ce qui le rend très naturel à lire, surtout pour ceux qui viennent du web classique.
On comprend en un coup d’œil ce qui va s’afficher.
<h1>Bonjour {user.name}</h1>
Cohérence
Avec JSX, tu écris la structure (HTML) et la logique (JS) dans un même fichier, dans un seul composant.
Cela rend ton code plus modulaire et plus facile à maintenir
const Product = ({ price }) => <p>Prix : {price} €</p>;
Dynamisme
JSX permet d’insérer n’importe quelle expression JavaScript entre des {} dans le HTML.
Tu peux afficher une variable, un calcul, un texte conditionnel, etc.
<p>{isLoggedIn ? "Bienvenue !" : "Veuillez vous connecter"}</p>
Performances
JSX est compilé automatiquement (par Babel) en appels optimisés comme React.createElement(...), ce qui :
- permet à React de construire un Virtual DOM
- compare les changements efficacement
- et met à jour uniquement les parties modifiées dans la page
Résultat : un site rapide, réactif, sans rechargement inutile.
En résumé
<h1>Hello</h1> // JSX que tu écris
↓
React.createElement('h1', null, 'Hello') // JS compilé
↓
React Element (objet JS)
↓
Virtual DOM (copie de la page)
↓
Mise à jour du DOM réel (seulement si nécessaire)
2. Interpolation
Utilise des accolades {} pour insérer du JS dans du JSX :
<h1>Hello {user.name}</h1>
3. Conditions
Avec && (shortcut operator)
{isLoggedIn && <p>Bienvenue !</p>}
Avec opérateur ternaire ? :
{isAdmin ? <AdminPanel /> : <UserPanel />}
Exemple pour les classes conditionnelles
className={`btn ${isActive && "active"}`}
ou plus complet :
className={`btn ${isActive ? "active" : "inactive"}`}
4. Listes / Mapping : rendering de listes avec key
Ne pas oublier la clé
<ul>
{items.map((item, i) => (
<li key={i}>{item}</li>
))}
</ul>
5. Fragments
Un fragment sert à grouper plusieurs éléments JSX sans ajouter de balise inutile dans le DOM, comme une <div>.
<>
<h1>Titre</h1>
<p>Texte</p>
</>
Pourquoi c’est utile ?
Imaginons que vous vouliez retourner plusieurs balises depuis un composant :
return (
<h1>Titre</h1>
<p>Paragraphe</p>
);
Ici React ne peut pas retourner plusieurs éléments frères sans les encapsuler.
Solution 1 (classique, mais pas toujours idéale)
return (
<div>
<h1>Titre</h1>
<p>Paragraphe</p>
</div>
);
Une <div> inutile dans le DOM peut perturber le CSS, le layout, ou polluer le HTML.
return (
<>
<h1>Titre</h1>
<p>Paragraphe</p>
</>
);
Un layout dans Next.js est l’équivalent moderne d’un include en PHP, mais pensé pour les interfaces React et le rendu côté client ou côté serveur.
Si tu viens du monde PHP, pense au layout.jsx comme à un fichier maître qui contient tous tes include() (menu, pied de page, etc.), et dans lequel tu placeras un espace réservé {children} pour afficher le contenu dynamique de chaque page.
Voici l’exemple d’un RootLayout
// app/layout.jsx
export default function RootLayout({ children }) {
return (
<html lang="fr">
<body>
<header>
<h1>Mon site</h1>
<nav>
<a href="/">Accueil</a> | <a href="/contact">Contact</a>
</nav>
</header>
<main>
{children} {/* Ici s'affiche le contenu des pages */}
</main>
<footer>
<p>© 2025 - Mon site</p>
</footer>
</body>
</html>
);
}
6. Fonctions dans JSX
const formatPrice = (price) => `${price} €`;
<p>{formatPrice(19.99)}</p>
Ici la fonction est déclarée. Elle reçoit un nombre (comme 19.99) et retourne une chaîne formatée, ici "19.99 €".
Cette fonction est appelée dans JSX. React remplace {formatPrice(19.99)} par "19.99 €" dans le HTML final.
C’est pratique pour réutiliser du code sans le recopier partout, pour transformer / formater des données avant affichage, pour garder du JSX propre et lisible.
7. Classes dynamiques (avec clsx ou classnames)
npm install clsx
import clsx from "clsx";
const className = clsx("text-blue-500", {
"font-bold": pathname === "/contact",
});
Contrairement à la méthode native, qui devient rapidement difficile à lire dès que plusieurs conditions s’enchaînent — avec un risque d’oubli d’espace ou de génération de valeurs comme undefined ou "false" — clsx offre une syntaxe plus claire, tout en étant plus légère et rapide que l’ancienne bibliothèque classnames.
const className = `text-blue-500 ${pathname === "/contact" ? "font-bold" : ""}`;
Ancienne méthode
import classNames from "classnames";
const className = classNames("text-blue-500", {
"font-bold": pathname === "/contact",
});
8. Entourer le JSX de parenthèses dans un return multi-ligne
En React, quand un composant est écrit avec return, il peut retourner une valeur unique (comme du JSX) mais si le JSX s’étale sur plusieurs lignes, il faut l’entourer de parenthèses pour que JavaScript le comprenne correctement.
Avec les parenthèses React comprend qu’il faut retourner tout ce bloc JSX.
return (
<div>
<h1>Hello</h1>
<p>World</p>
</div>
);
En JavaScript, si une instruction return est immédiatement suivie d’un saut de ligne, le moteur considère que la valeur retournée est vide (undefined) et ignore tout ce qui suit.
9. Conditions if
Dans JSX, tu ne peux pas écrire un if classique entre des accolades, car ce n’est pas une expression, mais une instruction. JSX n’accepte que des expressions à évaluer.
En JavaScript, une expression c’est du code qui renvoie une valeur.
2 + 3 // renvoie 5
"user" + "name" // renvoie "username"
isLoggedIn && "Bienvenue" // renvoie "Bienvenue" ou false
Une instruction c’est du code qui fait quelque chose, mais qui ne produit pas directement de valeur.
if (isLoggedIn) {
console.log("Bienvenue");
}
for (let i = 0; i < 5; i++) {
...
}
En JSX seules les expressions sont autorisées entre les accolades
<p>{isLoggedIn && "Bienvenue"}</p>
Comme JSX n’accepte pas les instructions comme if, il est toujours possible de les utiliser à l’extérieur du return, ou avant le JSX, dans la fonction du composant.
Méthode 1 en préparant l’affichage avant le return :
function Message({ isLoggedIn }) {
let content;
if (isLoggedIn) {
content = <p>Bienvenue !</p>;
} else {
content = <p>Connecte-toi.</p>;
}
return <div>{content}</div>;
}
Méthode 2 en utilisant une fonction ou logique en dehors du JSX
function UserGreeting({ user }) {
if (!user) {
return <p>Chargement...</p>; // instruction autorisée car c’est le return de la fonction
}
return (
<div>
<h1>Bonjour {user.name}</h1>
</div>
);
}
Méthode 3 : en transformant une instruction if en expression avec un ternaire
<p>{isLoggedIn ? "Bienvenue" : "Connecte-toi"}</p>
Tableau de transformation JSX
| Situation (logique souhaitée) | if interdit en JSX | Solution avec expression |
|---|---|---|
| Afficher un contenu si une condition est vraie | {if (cond) <p>Oui</p>} | {cond && <p> Oui </p> } |
| Afficher l’un ou l’autre contenu selon une condition | { if (cond) <p>Oui</p> else <p>Non</p> } | { cond ? <p>Oui</p> : <p>Non</p> } |
| Plusieurs conditions imbriquées | if (a) {...} else if (b) {...} else {...} | Utiliser if avant le return, ou un switch |
| Choisir dynamiquement une variable JSX à afficher | if (cond) el = <A /> else el = <B /> | Définir la variable avant le return, puis {el} |
10. class devient className=
En JavaScript, class est un mot-clé réservé. React utilise className à la place pour ne pas entrer en conflit avec le langage.
<div className="container"></div>
11. for= (dans une balise ) → devient htmlFor=
Là aussi, for est réservé en JavaScript (ex. : for (...) {}), donc JSX utilise htmlFor pour le champ de formulaire associé.
function ContactForm() {
return (
<form>
<label htmlFor="email" className="block mb-2 font-semibold">
Email
</label>
<input
type="email"
id="email"
name="email"
className="border px-3 py-2 rounded w-full"
placeholder="Entrez votre email"
/>
</form>
);
}
export default ContactForm;
12. Bonus : composants clients vs serveurs ("use client")
Depuis Next.js 13, un fichier .jsx ou .tsx est par défaut un composant serveur.
Quand tu crées un composant React dans Next.js, il est par défaut exécuté côté serveur (donc sur l’ordinateur qui héberge ton site). C’est très pratique pour les performances. Mais il y a un petit souci.
Certains outils de React, appelés « hooks » (useState, useEffect, usePathname, etc.)
ne fonctionnent que dans le navigateur, donc côté client.
En React, un hook est un outil intégré qui te permet d’ajouter des fonctionnalités dynamiques dans un composant sans avoir besoin d’écrire une classe.
Les hooks sont comme des super-pouvoirs que tu donnes à tes composants pour réagir à des changements, gérer des données, ou interagir avec le navigateur.
Le hook useState : pour gérer une valeur qui change
C’est le hook le plus utilisé. Il sert à créer une variable « vivante » qui peut changer quand l’utilisateur interagit avec la page.
"use client";
import { useState } from "react";
export default function Compteur() {
const [count, setCount] = useState(0);
return (
<div>
<p>Tu as cliqué {count} fois</p>
<button onClick={() => setCount(count + 1)}>Clique ici</button>
</div>
);
}
count est la valeur actuelle
setCount est la fonction qui permet de la modifier
useState(0) indique que la valeur de départ est 0
Le hook useEffect : pour réagir à des événements
Ce hook permet d’exécuter du code au bon moment (au chargement de la page, quand une donnée change, etc.).
"use client";
import { useEffect } from "react";
useEffect(() => {
console.log("Composant affiché !");
}, []);
Ici, useEffect agit comme : “Fais ceci une fois au chargement de la page.”
Le hook usePathname (Next.js) : pour récupérer l’URL actuelle
C’est un hook spécifique à Next.js, utile quand tu veux connaître sur quelle page se trouve l’utilisateur.
"use client";
import { usePathname } from "next/navigation";
const pathname = usePathname(); // "/dashboard", "/blog", etc.
Pourquoi « use client » est obligatoire ?
Tous ces hooks ont besoin du navigateur pour fonctionner, car ils dépendent :
- d’interactions utilisateur (
click,input, etc.) - ou de l’environnement du navigateur (
window,URL,localStorage, etc.)
Donc, tu dois déclarer tout en haut du fichier :
"use client";
Sans ça, Next.js croira que tu veux exécuter ton composant côté serveur, ce qui entraînera une erreur.
En conclusion
JSX n’est pas du HTML, et c’est justement ce qui le rend si puissant et structurant dans un projet React ou Next.js.
Mais pour en tirer pleinement parti, il est essentiel de bien comprendre ses particularités : expressions au lieu d’instructions, noms d’attributs adaptés, syntaxe déclarative et composition par composants.
Avec ces 10 points en tête, tu évites non seulement les erreurs les plus fréquentes, mais tu gagnes aussi en lisibilité, en maintenabilité… et en sérénité.
Que tu sois étudiant, développeur en reconversion ou formateur, cette fiche est conçue comme un repère de base, à consulter à chaque fois qu’un doute survient.
Et si tu veux aller plus loin, je t’invite à consulter mes autres ressources autour de React, Next.js et la pédagogie du développement web moderne.


