Chapitre 3 : Composants
Qu'est-ce qu'un composant ?
Un composant est une fonction JavaScript qui retourne du JSX :
function Welcome() {
return <h1>Bonjour !</h1>;
}
C'est tout. Une fonction qui retourne de l'UI.
Conventions de nommage
- PascalCase pour les noms de composants :
UserCard,LoginForm,NavigationMenu - Les composants commençant par une minuscule sont traités comme des balises HTML
// CORRECT
function UserCard() { ... }
<UserCard />
// INCORRECT - traité comme une balise HTML <usercard>
function userCard() { ... }
<userCard /> // Ne fonctionne pas !
Props : passer des données
Les props (properties) permettent de passer des données à un composant :
// Définition du composant avec props
function Welcome({ name }) {
return <h1>Bonjour, {name} !</h1>;
}
// Utilisation
<Welcome name="Jean" />
<Welcome name="Marie" />
Plusieurs props
function UserCard({ name, email, role }) {
return (
<div className="card">
<h2>{name}</h2>
<p>{email}</p>
<span>{role}</span>
</div>
);
}
<UserCard name="Jean" email="jean@example.com" role="Admin" />
Props avec valeur par défaut
function Button({ label, type = "button", disabled = false }) {
return (
<button type={type} disabled={disabled}>
{label}
</button>
);
}
<Button label="Envoyer" />
<Button label="Soumettre" type="submit" />
<Button label="Désactivé" disabled={true} />
Props de type différent
function Product({ name, price, inStock, tags, onClick }) {
return (
<div onClick={onClick}>
<h3>{name}</h3>
<p>{price} €</p>
{inStock && <span>En stock</span>}
<ul>
{tags.map(tag => <li key={tag}>{tag}</li>)}
</ul>
</div>
);
}
<Product
name="Laptop"
price={999}
inStock={true}
tags={['tech', 'promo']}
onClick={() => console.log('Cliqué')}
/>
| Type | Exemple |
|---|---|
| String | name="Jean" |
| Number | age={30} |
| Boolean | active={true} ou juste active |
| Array | items={[1, 2, 3]} |
| Object | user={{ name: 'Jean' }} |
| Function | onClick={() => {}} |
Props children
La prop spéciale children contient le contenu entre les balises ouvrante et fermante :
function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
<div className="card-body">
{children}
</div>
</div>
);
}
// Utilisation
<Card title="Mon titre">
<p>Ceci est le contenu de la carte.</p>
<button>Action</button>
</Card>
C'est très utile pour créer des composants "wrapper" ou "layout".
Composition de composants
Les composants peuvent utiliser d'autres composants :
function Avatar({ src, alt }) {
return <img className="avatar" src={src} alt={alt} />;
}
function UserInfo({ name, email }) {
return (
<div className="user-info">
<span className="name">{name}</span>
<span className="email">{email}</span>
</div>
);
}
function UserCard({ user }) {
return (
<div className="user-card">
<Avatar src={user.avatar} alt={user.name} />
<UserInfo name={user.name} email={user.email} />
</div>
);
}
function UserList({ users }) {
return (
<div className="user-list">
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
Hiérarchie : UserList -> UserCard -> Avatar + UserInfo
Props sont en lecture seule
Règle fondamentale : un composant ne doit jamais modifier ses props.
// INCORRECT - ne jamais faire ça !
function BadComponent({ user }) {
user.name = "Modifié"; // INTERDIT !
return <div>{user.name}</div>;
}
// CORRECT - les props sont immuables
function GoodComponent({ user }) {
return <div>{user.name}</div>;
}
Si vous devez modifier des données, utilisez l'état (useState - prochain module).
Déstructuration des props
Plusieurs façons de récupérer les props :
// 1. Déstructuration dans les paramètres (recommandé)
function UserCard({ name, email }) {
return <div>{name} - {email}</div>;
}
// 2. Déstructuration dans le corps
function UserCard(props) {
const { name, email } = props;
return <div>{name} - {email}</div>;
}
// 3. Sans déstructuration
function UserCard(props) {
return <div>{props.name} - {props.email}</div>;
}
Spread de props
Pour transférer toutes les props à un élément enfant :
function Button({ children, ...rest }) {
return (
<button className="btn" {...rest}>
{children}
</button>
);
}
// Utilisation - onClick et disabled sont passés au button
<Button onClick={handleClick} disabled={isLoading}>
Envoyer
</Button>
Organisation des fichiers
Convention SmartMaker : un composant par dossier avec index.jsx :
src/components/
├── UserCard/
│ └── index.jsx
├── UserList/
│ └── index.jsx
└── common/
├── Button/
│ └── index.jsx
└── Card/
└── index.jsx
// src/components/UserCard/index.jsx
export default function UserCard({ user }) {
return (
<div className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
}
// Import
import UserCard from 'src/components/UserCard';
Exercices
Exercice 1 : Créer un composant Button
Créer un composant Button qui accepte :
label: texte du boutonvariant: "primary" ou "secondary" (défaut: "primary")onClick: fonction à appeler au clic
Solution :
function Button({ label, variant = "primary", onClick }) {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{label}
</button>
);
}
// Utilisation
<Button label="Envoyer" onClick={() => console.log('Envoyé')} />
<Button label="Annuler" variant="secondary" onClick={handleCancel} />
Exercice 2 : Composition
Créer une structure de composants pour afficher une liste de produits :
ProductList: reçoit un tableau de produitsProductCard: affiche un produit (nom, prix)Price: affiche un prix formaté avec le symbole €
Solution :
function Price({ value }) {
return <span className="price">{value.toFixed(2)} €</span>;
}
function ProductCard({ product }) {
return (
<div className="product-card">
<h3>{product.name}</h3>
<Price value={product.price} />
</div>
);
}
function ProductList({ products }) {
return (
<div className="product-list">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
// Utilisation
const products = [
{ id: 1, name: 'Laptop', price: 999.99 },
{ id: 2, name: 'Phone', price: 699.50 }
];
<ProductList products={products} />
Points clés à retenir
- Composant = fonction qui retourne du JSX
- PascalCase pour les noms de composants
- Props : données passées au composant (lecture seule)
- children : contenu entre les balises
- Composition : composants qui utilisent d'autres composants
- Déstructuration :
function Component({ prop1, prop2 })
Récapitulatif du Module 2
Vous connaissez maintenant les bases de React :
| Concept | Description |
|---|---|
| JSX | Syntaxe pour écrire de l'UI en JavaScript |
| Composant | Fonction qui retourne du JSX |
| Props | Données passées à un composant |
| children | Contenu entre les balises |
| key | Identifiant unique pour les listes |
| Fragment | <></> pour retourner plusieurs éléments |
← Chapitre précédent | Retour au module | Module suivant : Hooks Fondamentaux ->