From 8a52c924495cbfe1a36e32ad491d5c99c89d1d54 Mon Sep 17 00:00:00 2001 From: matthieureynier Date: Fri, 26 Jun 2026 16:10:02 +0200 Subject: [PATCH] Contact: correction total likes a la suppression (sync jeux/likes) + explication reduce + champ console/plateforme --- CORRECTION_total_likes_et_reduce.md | 114 ++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 CORRECTION_total_likes_et_reduce.md diff --git a/CORRECTION_total_likes_et_reduce.md b/CORRECTION_total_likes_et_reduce.md new file mode 100644 index 0000000..d41c716 --- /dev/null +++ b/CORRECTION_total_likes_et_reduce.md @@ -0,0 +1,114 @@ +# 🔧 Correction — le total de likes ne baisse pas quand on supprime un jeu + +Avant la correction, prenons 5 minutes pour **vraiment** comprendre la ligne qui calcule le total, parce que c'est elle qui est au cƓur du bug : + +```jsx +const totalLikes = Object.values(likes).reduce((s, n) => s + n, 0); +``` + +--- + +## 🧠 D'abord : c'est quoi `.reduce` ? + +`reduce` sert Ă  **transformer un tableau en UNE seule valeur** (ici : la somme de tous les likes). + +Ton objet `likes` ressemble Ă  ça (la clĂ© = l'id du jeu, la valeur = son nombre de likes) : +```js +likes = { "1": 3, "2": 1, "4": 2 } +``` + +**Étape 1 — `Object.values(likes)`** prend seulement les **valeurs** et en fait un tableau : +```js +Object.values(likes) // → [3, 1, 2] +``` + +**Étape 2 — `.reduce(...)`** parcourt ce tableau et **accumule** au fur et Ă  mesure. + +```jsx +[3, 1, 2].reduce((s, n) => s + n, 0) +// â–Č â–Č â–Č +// | | └─ valeur de DÉPART de l'accumulateur (0) +// | └─ n = l'Ă©lĂ©ment en cours +// └─ s = l'accumulateur (ce qu'on a additionnĂ© jusqu'ici) +``` + +DĂ©roulĂ©, pas Ă  pas — imagine une **cagnotte** `s` qui commence Ă  0 et dans laquelle on verse chaque nombre : + +| tour | `s` (avant) | `n` (Ă©lĂ©ment) | `s + n` (aprĂšs) | +|---|---|---|---| +| dĂ©part | — | — | **0** | +| 1 | 0 | 3 | 3 | +| 2 | 3 | 1 | 4 | +| 3 | 4 | 2 | **6** | + +→ `totalLikes` vaut **6**. + +> 💡 À retenir : `reduce(callback, valeurDeDĂ©part)`. Le `callback` reçoit **(accumulateur, Ă©lĂ©ment)** et renvoie le **nouvel** accumulateur. Le `0` Ă  la fin, c'est la valeur de dĂ©part (une somme commence Ă  0 ; un produit commencerait Ă  1). + +> 🔎 C'est exactement la mĂȘme idĂ©e que ta moyenne d'annĂ©e : +> `jeux.reduce((s, j) => s + Number(j.annee), 0)` → lĂ , `s` accumule les **annĂ©es** de chaque jeu `j`. + +--- + +## 🐛 Le bug : supprimer un jeu n'enlĂšve pas ses likes du total + +Regarde ta fonction `supprimer` : +```jsx +function supprimer(id) { + setJeux(jeux.filter((j) => j.id !== id)); // ✅ enlĂšve le JEU +} +``` + +Tu retires bien le jeu du tableau `jeux`
 mais **tu ne touches pas Ă  l'objet `likes`**. Donc l'entrĂ©e du jeu supprimĂ© (par ex. `"2": 1`) **reste** dans `likes`. + +Et comme `totalLikes` fait `Object.values(likes).reduce(...)`, il **continue d'additionner les likes d'un jeu qui n'existe plus**. D'oĂč le total qui ne descend pas. 🎯 + +C'est un cas classique : tu as **deux objets Ă  garder synchronisĂ©s** (`jeux` et `likes`). Si tu supprimes dans l'un, tu dois supprimer dans l'autre. + +--- + +## ✅ La correction : supprimer le jeu **ET** ses likes + +`supprimer` doit aussi modifier `likes`. Or `likes`/`setLikes` vivent dans `App`. Le plus simple : **faire passer `setLikes` en props** jusqu'Ă  `Accueil` (comme tu passes dĂ©jĂ  `setJeux`). + +### 1. Dans `App.jsx`, ajoute `setLikes` aux props d'`Accueil` +```jsx + +``` + +### 2. Dans `Accueil.jsx`, rĂ©cupĂšre-le et complĂšte `supprimer` +```jsx +function Accueil({ jeux, setJeux, likes, setLikes, onLike }) { // 👈 setLikes ajoutĂ© + // ... + function supprimer(id) { + setJeux(jeux.filter((j) => j.id !== id)); // enlĂšve le jeu + setLikes((prev) => { + const copie = { ...prev }; // une COPIE (on ne modifie jamais l'ancien objet) + delete copie[id]; // on retire l'entrĂ©e de ce jeu + return copie; // on renvoie le nouvel objet + }); + } +} +``` + +> đŸ§© Pourquoi `{ ...prev }` puis `delete` ? MĂȘme rĂšgle d'**immutabilitĂ©** que partout en React : on ne modifie pas `prev` directement, on en fait une **copie**, on enlĂšve la clĂ© de la copie, et on renvoie la copie. React ne rĂ©affiche que si on lui donne un **nouvel** objet. + +**✅ Test :** like un jeu 3 fois (total = 3) → supprime ce jeu → le total **retombe** Ă  0, et le Hall of Fame ne le montre plus. F5 → toujours cohĂ©rent. + +--- + +## đŸ§č Petit bonus repĂ©rĂ© au passage + +Tes 5 jeux du `zelda.json` ont un champ **`console`** (`"console": "Game Boy Color"`), mais ton formulaire crĂ©e les nouveaux jeux avec un champ **`plateforme`**. Du coup : +- sur la carte tu affiches `props.plateforme` → pour les 5 jeux d'origine ça affiche **`undefined`** (ils n'ont pas `plateforme`, ils ont `console`) ; +- dans `Detail.jsx` tu affiches `jeu.console` → lĂ  c'est l'inverse, ça marche pour les 5 d'origine mais pas pour les jeux ajoutĂ©s. + +👉 Choisis **un seul** nom de champ (par ex. `console` partout) et utilise-le aux 3 endroits (le `nouveau` du formulaire, `Carte`, `Detail`). Une donnĂ©e = un seul nom, du dĂ©but Ă  la fin. + +> 💡 À retenir : quand deux Ă©tats dĂ©crivent la mĂȘme chose (un jeu et ses likes), une action sur l'un doit se rĂ©percuter sur l'autre — sinon ils **divergent**. Et un mĂȘme champ doit porter **le mĂȘme nom** partout dans l'appli.