Chapitre 2 : JSX
Qu'est-ce que JSX ?
JSX (JavaScript XML) est une extension de syntaxe qui permet d'écrire du HTML dans JavaScript :
- snippet.javascript
const element = <h1>Bonjour le monde !</h1>;
Ce n'est pas du HTML. C'est du JavaScript qui sera transformé en appels de fonctions React.
- snippet.javascript
// Ce JSX : const element = <h1 className="title">Bonjour</h1>; // Est transformé en : const element = React.createElement('h1', { className: 'title' }, 'Bonjour');
Vous n'avez pas besoin d'écrire React.createElement - le compilateur (Babel/Vite) le fait pour vous.
Différences avec HTML
className au lieu de class
class est un mot réservé en JavaScript :
- snippet.javascript
// HTML <div class="container"> // JSX <div className="container">
htmlFor au lieu de for
- snippet.javascript
// HTML <label for="email"> // JSX <label htmlFor="email">
Style en objet
- snippet.javascript
// HTML <div style="color: red; font-size: 16px;"> // JSX - objet avec camelCase <div style={{ color: 'red', fontSize: '16px' }}> // Ou avec une variable const styles = { color: 'red', fontSize: '16px' }; <div style={styles}>
Attributs en camelCase
- snippet.javascript
// HTML <button onclick="handleClick()"> <input tabindex="1"> // JSX <button onClick={handleClick}> <input tabIndex={1}>
Fermeture obligatoire des balises
- snippet.javascript
// HTML <img src="photo.jpg"> <input type="text"> <br> // JSX - toujours fermer <img src="photo.jpg" /> <input type="text" /> <br />
Expressions JavaScript dans JSX
Utilisez les accolades {} pour insérer du JavaScript :
Variables
- snippet.javascript
const name = "Jean"; const age = 30; return ( <div> <p>Nom : {name}</p> <p>Age : {age}</p> <p>Année de naissance : {2024 - age}</p> </div> );
Fonctions
- snippet.javascript
function formatName(user) { return `${user.firstName} ${user.lastName}`; } const user = { firstName: 'Jean', lastName: 'Dupont' }; return <h1>Bonjour, {formatName(user)} !</h1>;
Expressions, pas de statements
Dans les accolades, vous pouvez mettre des expressions (qui retournent une valeur), pas des statements (if, for, while).
- snippet.javascript
// CORRECT - expressions {name} {2 + 2} {formatName(user)} {isAdmin ? 'Admin' : 'User'} {items.length} // INCORRECT - statements {if (isAdmin) { return 'Admin' }} // Erreur ! {for (let i = 0; i < 10; i++) {}} // Erreur !
Conditions
Opérateur ternaire
Pour afficher une chose ou une autre :
- snippet.javascript
function Greeting({ isLoggedIn }) { return ( <div> {isLoggedIn ? ( <p>Bienvenue !</p> ) : ( <p>Veuillez vous connecter</p> )} </div> ); }
Opérateur &&
Pour afficher quelque chose ou rien :
- snippet.javascript
function Notification({ count }) { return ( <div> {count > 0 && ( <span className="badge">{count}</span> )} </div> ); }
Attention : {count && <span>...</span>} affichera 0 si count vaut 0, car 0 est une valeur “falsy” mais affichable. Préférez {count > 0 && ...}.
Variables pour les cas complexes
- snippet.javascript
function UserStatus({ user }) { let statusMessage; if (user.isAdmin) { statusMessage = <span className="admin">Administrateur</span>; } else if (user.isPremium) { statusMessage = <span className="premium">Premium</span>; } else { statusMessage = <span>Standard</span>; } return <div>{statusMessage}</div>; }
Boucles avec map()
Pour afficher une liste, utilisez map() :
- snippet.javascript
function UserList({ users }) { return ( <ul> {users.map(user => ( <li key={user.id}> {user.name} </li> ))} </ul> ); }
L'attribut key
Obligatoire pour les listes. Permet à React d'identifier chaque élément :
- snippet.javascript
// CORRECT - ID unique {users.map(user => ( <li key={user.id}>{user.name}</li> ))} // ACCEPTABLE - si pas d'ID, utiliser l'index (moins performant) {items.map((item, index) => ( <li key={index}>{item}</li> ))} // INCORRECT - pas de key {users.map(user => ( <li>{user.name}</li> // Warning React ! ))}
Comparaison avec PHP
- snippet.php
// PHP <?php foreach ($users as $user): ?> <li><?= $user['name'] ?></li> <?php endforeach; ?>
- snippet.javascript
// React {users.map(user => ( <li key={user.id}>{user.name}</li> ))}
Fragments
Un composant doit retourner un seul élément racine. Si vous ne voulez pas ajouter de <div> inutile, utilisez un Fragment :
- snippet.javascript
// INCORRECT - plusieurs éléments racine function UserInfo({ user }) { return ( <h1>{user.name}</h1> <p>{user.email}</p> // Erreur ! ); } // CORRECT - avec Fragment function UserInfo({ user }) { return ( <> <h1>{user.name}</h1> <p>{user.email}</p> </> ); } // Ou la syntaxe longue import { Fragment } from 'react'; function UserInfo({ user }) { return ( <Fragment> <h1>{user.name}</h1> <p>{user.email}</p> </Fragment> ); }
Exercices
Exercice 1 : Convertir en JSX
Convertir ce HTML en JSX :
- snippet.html
<div class="card"> <img src="photo.jpg" alt="Photo"> <label for="name">Nom :</label> <input type="text" id="name" tabindex="1"> <button onclick="save()">Sauvegarder</button> </div>
Solution :
- snippet.javascript
<div className="card"> <img src="photo.jpg" alt="Photo" /> <label htmlFor="name">Nom :</label> <input type="text" id="name" tabIndex={1} /> <button onClick={save}>Sauvegarder</button> </div>
Exercice 2 : Affichage conditionnel
Créer un composant qui affiche :
- “Chargement…” si
loadingest true - “Aucun résultat” si
itemsest vide - La liste des items sinon
Solution :
- snippet.javascript
function ItemList({ loading, items }) { if (loading) { return <p>Chargement...</p>; } if (items.length === 0) { return <p>Aucun résultat</p>; } return ( <ul> {items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> ); }
Points clés à retenir
- JSX n'est pas HTML : c'est du JavaScript transformé
- className au lieu de class, htmlFor au lieu de for
- Accolades
{}pour insérer du JavaScript - Ternaire
? :ou && pour les conditions - map() pour les boucles, avec une key unique
- Fragments
<></>pour retourner plusieurs éléments
← Chapitre précédent | Retour au module | Chapitre suivant : Composants →