Session BRE05 Help

Les classiques des composants React

Exercice 0

Vous allez faire tous les exercices sur le même projet React, pour chaque exercice, créez le composant dans un fichier .jsx séparé et appelez le dans le composant App.

  • Créez un repository public avec un README sur GitHub, appelez-le bre05-react-soutien

  • Clonez-le dans le dossier sites/react de votre IDE.

  • Dans le dossier bre05-react-soutien:

    • Créez un projet appelé soutien avec npm-create-vite

    • Videz le fichier src/index.css

    • Remplacez le code du fichier App.css avec le code suivant :

:root { --primary: #646cff; --bg: #f9f9f9; --text: #213547; --border: #ddd; --white: #ffffff; } body { font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; background-color: var(--bg); color: var(--text); padding: 2rem; } .exercise-container { max-width: 600px; margin: 2rem auto; padding: 1.5rem; background: var(--white); border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } button { background-color: var(--primary); color: white; border: none; padding: 0.6rem 1.2rem; border-radius: 4px; cursor: pointer; transition: opacity 0.2s; } button:hover { opacity: 0.8; } button:disabled { background-color: #ccc; cursor: not-allowed; } input[type="text"], select, textarea { width: 100%; padding: 8px; margin: 10px 0; border: 1px solid var(--border); border-radius: 4px; box-sizing: border-box; } /* Utilitaires pour les onglets et listes */ .flex-row { display: flex; gap: 10px; margin-bottom: 1rem; } .hidden { display: none; } .active-tab { border-bottom: 3px solid var(--primary); font-weight: bold; }

Exercice 1 : ReadMore

Voici le code HTML de votre composant :

<div class="exercise-container"> <img src="https://images.unsplash.com/photo-1507525428034-b723cf961d3e?auto=format&fit=crop&w=600&q=80" alt="Plage" style="width:100%; border-radius:4px; margin-bottom:1rem;"/> <h2>Les trésors cachés de Bali</h2> <p> Bali, l'île des Dieux, offre bien plus que ses plages célèbres. Entre les rizières en terrasse d'Ubud et les temples sacrés nichés sur les falaises d'Uluwatu, chaque recoin raconte une histoire. <span class="content-extra"> Ne manquez pas la cascade de Sekumpul, souvent oubliée des touristes, qui nécessite une randonnée de 40 minutes mais offre un spectacle naturel époustouflant au lever du soleil. </span> </p> <button>Lire la suite</button> </div>

Situation de départ du ReadMore:

Un titre, une image et un premier paragraphe sont visibles. Un second paragraphe (.content-extra) est présent dans le code.

Objectif du ReadMore :

  • Créez un état isVisible (initialisé à false).

  • Utilisez cet état pour afficher ou masquer le second paragraphe (rendu conditionnel).

  • Action : Au clic sur le bouton, l'état isVisible doit passer à true.

  • Dynamisme : Si isVisible est vrai, le texte du bouton doit devenir "Réduire", sinon il affiche "Lire la suite".

Exercice 2 : Onglets

Voici le code HTML de votre composant :

<div class="exercise-container"> <div class="flex-row"> <button class="active-tab">Description</button> <button>Spécifications</button> <button>Avis (12)</button> </div> <div class="tab-content"> <p>Le nouveau Casque <strong>NovaSound X1</strong> redéfinit l'excellence audio. Équipé de haut-parleurs en néodyme de 40 mm, il offre une clarté exceptionnelle des aigus et des basses profondes.</p> <p>Sa technologie de réduction de bruit active (ANC) analyse le bruit ambiant 1000 fois par seconde pour vous isoler parfaitement, que vous soyez dans le métro ou dans un bureau open-space.</p> </div> <div class="tab-content"> <ul style="list-style: none; padding: 0;"> <li style="margin-bottom: 8px;"><strong>Autonomie :</strong> 40h (ANC activé) / 55h (Standard)</li> <li style="margin-bottom: 8px;"><strong>Poids :</strong> 250g (Design ultra-léger)</li> <li style="margin-bottom: 8px;"><strong>Connectivité :</strong> Bluetooth 5.2 et Jack 3.5mm</li> <li style="margin-bottom: 8px;"><strong>Charge :</strong> USB-C (10 min = 5h d'écoute)</li> </ul> </div> <div class="tab-content"> <div style="border-left: 3px solid var(--primary); padding-left: 15px; margin-bottom: 15px;"> <p style="margin: 0; font-weight: bold;">⭐⭐⭐⭐⭐ - Sophie L.</p> <p style="margin: 5px 0; font-style: italic;">"Le confort est incroyable, même après 4h de visio. Le son est très équilibré."</p> </div> <div style="border-left: 3px solid var(--primary); padding-left: 15px;"> <p style="margin: 0; font-weight: bold;">⭐⭐⭐⭐ - Marc K.</p> <p style="margin: 5px 0; font-style: italic;">"Excellente réduction de bruit. Un peu cher, mais la qualité est là."</p> </div> </div> </div>

Situation de départ des onglets

Trois boutons en haut et une zone de contenu en bas.

Objectif des onglets :

  • Créez un état currentTab (initialisé à "description").

  • Associez chaque bouton à une valeur : "description", "specs", "avis".

  • Action : Au clic sur un bouton, mettez à jour currentTab avec la valeur correspondante.

  • Rendu : Affichez le bloc HTML de la description SI currentTab est égal à "description", et ainsi de suite pour les autres.

  • Style : Appliquez la classe CSS active-tab au bouton uniquement si son nom correspond à l'état currentTab.

Exercice 3 : formulaire conditionné

Voici le code HTML de votre composant :

<div class="exercise-container"> <h3>Inscription au Meetup React</h3> <label>Régime alimentaire :</label> <select> <option value="none">Sans restriction</option> <option value="vege">Végétarien</option> <option value="vegan">Végétalien</option> <option value="autre">Autre (Allergies...)</option> </select> <div class="conditional-field"> <label>Merci de préciser vos allergies :</label> <textarea placeholder="Ex: Arachides, Gluten..."></textarea> </div> <button style="margin-top:1rem; width:100%;">Confirmer l'inscription</button> </div>

Situation de départ du formulaire conditionné

Un menu déroulant (<select>) avec plusieurs options, dont une valeur "autre".

Objectif du formulaire conditionné

  • Créez un état choice pour stocker la valeur sélectionnée du <select>.

  • Liez cet état au champ avec l'attribut value et l'événement onChange.

  • Condition : Le champ <textarea> (précisions) ne doit s'afficher dans le DOM que SI choice === "autre".

Exercice 4 Champ de recherche

Voici le code HTML de votre composant :

<div class="exercise-container"> <h3>Annuaire de l'équipe</h3> <input type="text" placeholder="Rechercher un collaborateur (ex: 'Alice' ou 'Dev')..." /> <ul style="list-style: none; padding: 0;"> <li style="padding: 10px; border-bottom: 1px solid #eee;"> <strong>Alice Martin</strong> - <small>Lead Développeuse</small> </li> <li style="padding: 10px; border-bottom: 1px solid #eee;"> <strong>Bob Durand</strong> - <small>UX Designer</small> </li> <li style="padding: 10px; border-bottom: 1px solid #eee;"> <strong>Charlie Leroy</strong> - <small>Product Manager</small> </li> </ul> </div>

Les données de l'exercice :

const users = [ { id: 1, name: "Alice Martin", role: "Lead Développeuse" }, { id: 2, name: "Bob Durand", role: "UX Designer" }, { id: 3, name: "Charlie Leroy", role: "Product Manager" }, { id: 4, name: "Diane Petit", role: "Développeuse Front-end" } ];

Situation de départ du champ de recherche

Un tableau d'objets users (fourni) et un champ de texte.

Objectif du champ de recherche

  • Créez un état searchTerm (initialisé par une chaîne vide "").

  • Liez cet état à l'input de recherche (value et onChange).

  • Logique : Créez une variable temporaire qui filtre le tableau users : ne gardez que les utilisateurs dont le nom contient les lettres de searchTerm.

  • Rendu : Utilisez .map() sur ce tableau filtré pour générer les <li>.

Exercice 5 : Billetterie

Le HTML de votre composant :

<div class="exercise-container"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div> <h3 style="margin:0;">Billet Adulte</h3> <p style="color: #666; margin: 5px 0;">Exposition "L'Art de demain" - 15€</p> </div> <div class="flex-row" style="align-items: center;"> <button> - </button> <span style="min-width: 30px; text-align: center; font-weight: bold;">1</span> <button> + </button> </div> </div> <hr style="border: 0; border-top: 1px solid #eee; margin: 15px 0;" /> <div style="text-align: right;"> <strong>Total : 15€</strong> </div> </div>

Situation de départ de la billetterie

Un prix fixe (15€), un bouton -, un bouton +, et un affichage de la quantité.

Objectif de la billetterie

  • Créez un état quantity (initialisé à 1).

  • Actions : Le bouton + augmente la quantité de 1. Le bouton - la diminue de 1.

  • Contraintes :

    • Désactivez le bouton - (attribut disabled) si la quantité est égale à 1.

    • Désactivez le bouton + si la quantité est égale à 10.

  • Calcul : Affichez le total en multipliant en direct : {quantity * 15}€.

06 February 2026