diff --git a/TUTO_total_likes.md b/TUTO_total_likes.md new file mode 100644 index 0000000..e7046f3 --- /dev/null +++ b/TUTO_total_likes.md @@ -0,0 +1,109 @@ +# 🧩 Tuto pas à pas — le parent qui additionne les likes des enfants + +Tu cherches à faire **remonter** les likes : chaque `Carte` a son compteur, et `App` (le parent) affiche le **total**. C'est exactement le bon objectif 👍. Il te manque **une seule ligne** — et je veux surtout que tu comprennes **pourquoi**. + +--- + +## 🔍 D'abord, pourquoi ton total reste à 0 + +Regarde le bouton dans ta `Carte` : + +```jsx + +``` + +Quand on clique, tu fais `setLikes(likes + 1)` → ça met à jour **le compteur de la carte**. ✅ +Mais… tu n'as **jamais** prévenu le parent ! La fonction `onLike` que `App` t'a donnée en prop n'est **jamais appelée**. Donc `App` ne sait pas qu'on a liké → `total` reste à 0. + +> 🧠 **L'idée à comprendre :** un enfant **ne peut pas** modifier directement l'état du parent. Le parent lui **prête une fonction** (`onLike`), et l'enfant doit **l'appeler** au bon moment. C'est l'enfant qui dit « hé, on m'a likée ! » — le parent décide quoi en faire. + +--- + +## 🪜 La correction, étape par étape + +### Étape 1 — le parent a déjà tout (rien à changer) +Dans `App.jsx`, tu as déjà : +```jsx +const [total, setTotal] = useState(0); +// ... + setTotal((t) => t + 1)} /> +// ... +

Total de likes : {total}

+``` +Le parent tient le `total` et passe une fonction `onLike` à **chaque** carte. ✅ + +### Étape 2 — l'enfant doit APPELER `onLike` (la ligne qui manque) +Dans `Carte`, le bouton doit faire **deux choses** au clic : augmenter **son** compteur **et** prévenir le parent. + +```jsx + +``` + +> 🔎 Deux instructions dans le `onClick` → on les met entre accolades `{ ... }` avec un `;` entre les deux. C'est une petite fonction qui fait deux choses à la suite. + +**✅ Test :** clique sur le ❤️ d'une carte → **son** compteur monte **et** le « Total de likes » en haut monte aussi. Clique sur une autre carte → le total continue de grimper. + +--- + +## 🎓 Ta question : pourquoi chaque bouton démarre avec la **même** valeur ? + +C'est une **excellente** question, et la réponse, c'est **l'initialisation** de `useState`. + +```jsx +const [likes, setLikes] = useState( + () => Number(localStorage.getItem("likes-" + props.id)) || 0 +); +``` + +### 1. La valeur dans `useState(...)` n'est qu'un **point de départ** +L'argument que tu passes à `useState(...)` est la **valeur initiale** : React l'utilise **une seule fois**, au tout **premier affichage** de la carte, pour démarrer le compteur. Ensuite, c'est `setLikes(...)` qui prend le relais — l'initialisation **ne sert plus**. + +> 🧠 `useState(valeurDeDépart)` = « démarre à cette valeur, **la première fois seulement** ». Après, l'état vit sa vie. + +### 2. Chaque `` est **indépendante** (elle ne partage rien) +Chaque fois que tu écris ``, React crée une **instance séparée**, avec son **propre** `likes`. Liker la carte n°1 ne touche pas la carte n°2 : ce sont des compteurs distincts. + +### 3. Alors pourquoi elles affichent toutes la même valeur au départ ? +Parce qu'elles exécutent toutes **le même calcul d'initialisation**, et qu'au **premier lancement**, `localStorage` est **vide** : + +- `localStorage.getItem("likes-" + props.id)` → renvoie `null` (rien n'est encore stocké) +- `Number(null)` → `0`, donc `|| 0` → **0** + +→ **toutes** les cartes démarrent à **0**. Ce n'est pas qu'elles « partagent » une valeur : c'est qu'elles **partent toutes de la même situation** (rien en mémoire). C'est comme 4 personnes qui commencent un jeu : elles ont toutes 0 point au début, mais chacune marque ses propres points ensuite. + +> 💡 **La preuve que c'est bien indépendant et par-carte :** like la carte n°1, **recharge la page (F5)**. La carte n°1 retrouve **sa** valeur (lue dans `localStorage` à la clé `likes-1`), les autres restent à 0. Chaque carte a donc bien **sa propre** initialisation, basée sur **son** `id`. + +--- + +## ⚠️ Un piège que tu as déjà senti (commit « buggy ») + +Tu as remarqué : les likes par carte **survivent au rechargement** (ils sont dans `localStorage`), **mais le `total` repart à 0** après un F5. Normal : le `total` du parent n'est **pas** stocké, et il n'est pas **recalculé** à partir des cartes — il ne fait que s'incrémenter aux clics. + +Pour l'instant, **c'est OK** : ton objectif était de faire **remonter** un like vers le parent (le pattern callback ci-dessus), et c'est réussi. +> 🔭 Pour aller plus loin (plus tard) : il existe une version plus robuste où le **total se recalcule** tout seul à partir des likes (une seule « source de vérité »). On en reparlera — c'est l'étape d'après. + +--- + +## 🧹 Petit nettoyage + +Dans `Carte`, tu as un effet **vide** qui ne sert à rien : +```jsx +useEffect(() => {}, [likes]); // ❌ à supprimer +``` +Enlève-le, il ne fait rien. + +--- + +## ✅ Récap + +- Le parent **prête** une fonction (`onLike`) ; l'enfant doit **l'appeler** → c'est la ligne `props.onLike()` qui te manquait. +- Au clic : l'enfant met à jour **son** état **et** appelle `props.onLike()`. +- `useState(x)` = valeur de départ, utilisée **une fois**. Chaque carte est **indépendante** ; elles démarrent toutes pareil parce qu'au premier lancement la mémoire est vide (toutes à 0). +- Supprime le `useEffect` vide.