BaliseTonSite

State & Événements

Rends tes composants vivants et interactifs au fil du jeu.

3.1Pourquoi une variable classique ne suffit pas

Si tu crées une variable locale classique dans ton composant et que tu essaies de la modifier lors d'un clic, il ne se passera rien à l'écran :

TSXtsx
// ❌ Pourquoi ça ne marche pas :
function CompteurInactif() {
  let score = 0; // variable locale classique

  const incrementer = () => {
    score++;
    console.log("Score en mémoire :", score); // Le score change en mémoire...
  };

  return (
    <div>
      <p>Score : {score}</p> {/* ...mais React ne redessine pas le composant ! */}
      <button onClick={incrementer}>+1</button>
    </div>
  );
}

React ne surveille pas tes variables locales. Il n'a aucun moyen de savoir qu'elles ont changé, et il ne déclenchera pas de mise à jour visuelle. Pour cela, tu dois utiliser un **Hook** spécial appelé useState.

3.2Le Hook useState : enregistrer ses stats auprès de React

Un "Hook" est une fonction spéciale de React qui permet de "se brancher" sur ses fonctionnalités internes. useState permet de déclarer une variable d'état que React va surveiller de près.

TSXtsx
import { useState } from "react";

function CompteurInteractif() {
  // useState renvoie toujours un tableau avec 2 éléments :
  // 1. La valeur actuelle de ton état
  // 2. La fonction "setter" pour modifier cette valeur
  const [score, setScore] = useState(0); // 0 est la valeur de départ

  return (
    <div>
      <p>Score actuel : {score}</p>
      
      {/* On utilise obligatoirement le setter pour modifier la valeur */}
      <button onClick={() => setScore(score + 1)}>
        +1 Point
      </button>
    </div>
  );
}

Règle de fer : N'écris JAMAIS score = score + 1. Modifie toujours ton état en passant par son setter (setScore). Si tu tentes de modifier directement la variable, React ne détectera pas le changement, et l'écran restera figé.

3.3Sous le capot : le cycle de rendu (Trigger - Render - Commit)

Pour bien comprendre pourquoi ton écran se met à jour, il faut visualiser le cycle en 3 étapes que React exécute à chaque changement d'état :

// Le cycle de vie d'une mise à jour :
1. TRIGGER (Le déclencheur) :
Tu appelles la fonction modificatrice, par exemple setScore(score + 1). C'est le signal de départ pour React.
⬇️
2. RENDER (Le dessin) :
React appelle à nouveau ton composant. Il exécute la fonction pour voir à quoi ressemble la nouvelle structure de JSX retournée en fonction du nouveau score.
⬇️
3. COMMIT (L'application) :
React compare le nouveau JSX avec l'ancien, identifie ce qui a changé, et applique uniquement ces changements sur le DOM réel du navigateur. L'affichage se met à jour.

3.4Les événements en React : interagir avec l'utilisateur

Les événements React fonctionnent de façon très similaire aux événements HTML standards, mais s'écrivent en camelCase (comme onClick, onChange, onSubmit). Tu leur passes une référence de fonction à exécuter :

TSXtsx
function Arena() {
  const attaquer = () => {
    alert("Coup d'épée lancé ! ⚔️");
  };

  return (
    <div>
      {/* 1. Référence de fonction : on donne le nom de la fonction,
          React l'exécutera lors du clic. */}
      <button onClick={attaquer}>Attaquer</button>

      {/* 2. Fonction inline : pratique pour des lignes courtes */}
      <button onClick={() => console.log("Potion bue")}>
        Boire potion
      </button>
    </div>
  );
}

Le piège classique : N'écris jamais onClick={attaquer()} avec des parenthèses dans ton JSX. Si tu fais cela, la fonction s'exécutera immédiatement pendant le rendu initial de la page, avant même que l'utilisateur ne clique sur quoi que ce soit. Passe toujours la référence de la fonction : onClick={attaquer}.

3.5Les formulaires contrôlés : la source unique de vérité

En HTML classique, c'est le navigateur qui stocke la valeur de ce que tu tapes dans un champ de texte. En React, on préfère que ce soit le **state** qui contrôle tout. C'est le concept de **formulaire contrôlé** :

TSXtsx
import { useState } from "react";

function InscriptionGuilde() {
  const [pseudo, setPseudo] = useState("");

  const validerFormulaire = (e: React.FormEvent) => {
    e.preventDefault(); // Empêche le navigateur de recharger la page
    console.log("Bienvenue dans la guilde,", pseudo);
  };

  return (
    <form onSubmit={validerFormulaire}>
      <label>Choisis ton pseudo :</label>
      <input
        type="text"
        // 1. La valeur affichée est dictée par le state
        value={pseudo}
        // 2. À chaque touche tapée, on met à jour le state
        onChange={(e) => setPseudo(e.target.value)}
        placeholder="Ex: Legolas"
      />
      <button type="submit">Rejoindre</button>
    </form>
  );
}

3.6Immutabilité : modifier des tableaux et objets dans le State

React compare l'ancien et le nouvel état en vérifiant leur **référence en mémoire** (par égalité stricte `===`). Si tu modifies directement le contenu d'un tableau ou d'un objet existant, sa référence en mémoire ne change pas. React pensera que l'état n'a pas bougé et refusera de mettre à jour l'écran !

C'est la règle de l'**immutabilité**. Tu dois toujours créer une **copie complète** de ton tableau ou de ton objet avant de l'envoyer au setter. On utilise pour cela le spread operator (...) :

TSXtsx
import { useState } from "react";

interface Item {
  id: number;
  nom: string;
}

function Inventaire() {
  const [sac, setSac] = useState<Item[]>([
    { id: 1, nom: "Épée longue" },
    { id: 2, nom: "Bouclier en bois" }
  ]);

  // ✅ CORRECT : Ajouter un item (on crée un nouveau tableau)
  const ajouterItem = (nomNouvelItem: string) => {
    const nouvelItem = { id: Date.now(), nom: nomNouvelItem };
    setSac([...sac, nouvelItem]); // On déverse l'ancien sac + le nouvel item
  };

  // ✅ CORRECT : Supprimer un item (filter renvoie un nouveau tableau)
  const jeterItem = (idAArroser: number) => {
    setSac(sac.filter(item => item.id !== idAArroser));
  };

  // ❌ INCORRECT (ne provoquera aucun rendu) :
  // sac.push({ id: 3, nom: "Potion" });
  // setSac(sac); // La référence mémoire du tableau 'sac' n'a pas changé !
}

Verifie tes acquis

3 questions pour valider ce chapitre

1. Pourquoi ne peut-on pas modifier le state directement (ex: count = 5) ?

Valide et sauvegarde ce chapitre

Ne perds pas le fil de ton apprentissage. Chaque QCM terminé sauvegarde ton score. Crée ton profil gratuitement pour débloquer toutes les évaluations du site et retrouver tes résultats plus tard.

Commencer l'aventure
Déjà membre ?Connecte-toi