05 — State (useState)

🔍 Props vs State

PropsState
Qui le définit ?Le parentLe composant lui-même
Modifiable ?Non (lecture seule)Oui (via setter)
Déclenche un re-rendu ?Oui (si changé par le parent)Oui (à chaque mise à jour)
UsageConfigurer un enfantDonnées dynamiques internes

⚡ Le Hook useState

useState est un hook qui permet d'ajouter un état local à un composant fonctionnel.

const { useState } = React; // ou : React.useState

function Compteur() {
    // Déclare une variable d'état "count" initialisée à 0
    // setCount est la fonction pour la modifier
    const [count, setCount] = useState(0);
    //     ^       ^                 ^
    //     |       |                 valeur initiale
    //     |       fonction pour mettre à jour
    //     valeur actuelle

    return (
        <div>
            <p>Compteur : {count}</p>
            <button onClick={() => setCount(count + 1)}>+1</button>
        </div>
    );
}

📐 Comment ça marche ?

  1. useState(0) déclare un état initialisé à 0.
  2. Il retourne un tableau de 2 éléments : [valeur, setter].
  3. Quand on appelle setCount(newValue), React re-rend le composant avec la nouvelle valeur.
  4. Le composant est « rappelé » par React, mais useState se souvient de la valeur entre les rendus.

🔄 Mise à jour fonctionnelle

Si la nouvelle valeur dépend de l'ancienne, utiliser la forme fonctionnelle :

// ⚠️ Peut poser problème si appelé plusieurs fois rapidement
setCount(count + 1);

// ✅ Forme fonctionnelle — toujours correcte
setCount(prevCount => prevCount + 1);

// Pourquoi ? Parce que "count" peut être périmé si React
// a batché plusieurs mises à jour ensemble.
💡 Règle simple : Si le nouvel état dépend de l'ancien → utilise la forme fonctionnelle prev => ...

📦 Différents types de state

// Nombre
const [age, setAge] = useState(25);

// String
const [nom, setNom] = useState("Alice");

// Booléen
const [visible, setVisible] = useState(true);

// Tableau
const [fruits, setFruits] = useState(['pomme', 'poire']);

// Objet
const [user, setUser] = useState({ nom: "Alice", age: 30 });

// null (pas encore chargé)
const [data, setData] = useState(null);

⚠️ Mettre à jour un objet ou tableau

On ne modifie jamais directement l'état. On crée une nouvelle copie :

// ❌ Mutation directe — React ne détecte pas le changement
user.nom = "Bob";
setUser(user);

// ✅ Nouvelle copie avec spread
setUser({ ...user, nom: "Bob" });

// ❌ Mutation directe d'un tableau
fruits.push('banane');
setFruits(fruits);

// ✅ Nouveau tableau
setFruits([...fruits, 'banane']);         // Ajouter
setFruits(fruits.filter(f => f !== 'pomme')); // Supprimer
setFruits(fruits.map(f => f === 'pomme' ? 'mangue' : f)); // Modifier
⚠️ Immutabilité : React compare par référence. Si on modifie l'objet existant, la référence ne change pas → pas de re-rendu !

📏 Règles des Hooks

  1. Toujours au niveau supérieur — pas dans un if, for, ou fonction imbriquée.
  2. Uniquement dans les composants React ou dans un custom hook.
// ❌ INTERDIT
function MonComposant() {
    if (condition) {
        const [val, setVal] = useState(0); // dans un if !
    }
}

// ✅ CORRECT
function MonComposant() {
    const [val, setVal] = useState(0); // au top level
    if (condition) {
        // utiliser val ici c'est OK
    }
}

🔢 Plusieurs useState

function Formulaire() {
    const [nom, setNom] = useState("");
    const [email, setEmail] = useState("");
    const [age, setAge] = useState(0);
    const [accepte, setAccepte] = useState(false);

    // Chaque état est indépendant
    // ...
}

🚀 Démo interactive

▼ Plusieurs exemples de useState en action

📝 Résumé

← 04 — Props 06 — Événements →