Listes & Rendu Conditionnel
Affiche des données dynamiquement et montre/cache des éléments.
4.1Afficher une liste avec map()
Pour afficher une liste en React, tu utilises .map() pour transformer chaque élément de ton tableau en JSX :
function ListeCoequipiers() {
const equipe = ["Alice", "Bob", "Charlie", "Diana"]
return (
<ul>
{equipe.map((nom) => (
<li key={nom}>{nom}</li>
))}
</ul>
)
}
// Avec des objets
function ListeProduits() {
const produits = [
{ id: 1, nom: "Clavier", prix: 79 },
{ id: 2, nom: "Souris", prix: 49 },
{ id: 3, nom: "Écran", prix: 299 },
]
return (
<div>
{produits.map((produit) => (
<div key={produit.id} className="carte">
<h3>{produit.nom}</h3>
<p>{produit.prix} €</p>
</div>
))}
</div>
)
}4.2Les keys : indispensables !
React a besoin d'un identifiant unique (key) pour chaque élément d'une liste. C'est comme ça qu'il sait quoi mettre à jour quand la liste change :
// ✅ BON : key unique et stable
{produits.map((p) => (
<CarteProduit key={p.id} nom={p.nom} prix={p.prix} />
))}
// ⚠️ ACCEPTABLE si la liste ne change jamais
{noms.map((nom, index) => (
<li key={index}>{nom}</li>
))}
// ❌ MAUVAIS : pas de key → warning React
{produits.map((p) => (
<CarteProduit nom={p.nom} />
))}4.3Rendu conditionnel : if / else en JSX
En JSX, tu ne peux pas écrire if/else directement. Mais tu as 3 techniques :
Technique 1 : l'opérateur &&
// Si la condition est vraie → affiche le JSX
function Notification({ count }: { count: number }) {
return (
<div>
<h2>Notifications</h2>
{count > 0 && (
<span className="badge">{count} nouvelles</span>
)}
</div>
)
}Technique 2 : le ternaire
// Condition ? siVrai : siFaux
function Statut({ estConnecte }: { estConnecte: boolean }) {
return (
<div>
{estConnecte ? (
<p>Bienvenue ! <button>Déconnexion</button></p>
) : (
<p>Veuillez vous connecter. <button>Connexion</button></p>
)}
</div>
)
}Technique 3 : return anticipé
// Pour des cas plus complexes
function PageProfil({ user, isLoading, error }: {
user: any
isLoading: boolean
error: string | null
}) {
if (isLoading) return <p>Chargement...</p>
if (error) return <p>Erreur : {error}</p>
if (!user) return <p>Utilisateur introuvable</p>
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
)
}4.4Exemple complet : Todo List filtrable
On combine liste + state + conditionnel dans un exemple concret :
import { useState } from 'react'
function TodoApp() {
const [todos, setTodos] = useState([
{ id: 1, text: "Apprendre React", done: true },
{ id: 2, text: "Créer un projet", done: false },
{ id: 3, text: "Déployer en prod", done: false },
])
const [filtre, setFiltre] = useState<"tous" | "actifs" | "faits">("tous")
// Filtrer selon le filtre actif
const todosFiltres = todos.filter(todo => {
if (filtre === "actifs") return !todo.done
if (filtre === "faits") return todo.done
return true
})
const toggleTodo = (id: number) => {
setTodos(todos.map(t =>
t.id === id ? { ...t, done: !t.done } : t
))
}
return (
<div>
{/* Boutons de filtre */}
<div>
{(["tous", "actifs", "faits"] as const).map(f => (
<button
key={f}
onClick={() => setFiltre(f)}
style={{ fontWeight: filtre === f ? "bold" : "normal" }}
>
{f}
</button>
))}
</div>
{/* Liste filtrée */}
{todosFiltres.length === 0 ? (
<p>Aucune tâche à afficher.</p>
) : (
<ul>
{todosFiltres.map(todo => (
<li
key={todo.id}
onClick={() => toggleTodo(todo.id)}
style={{ textDecoration: todo.done ? "line-through" : "none" }}
>
{todo.text}
</li>
))}
</ul>
)}
{/* Stats */}
<p>{todos.filter(t => t.done).length}/{todos.length} terminées</p>
</div>
)
}