Contact: correction total likes a la suppression (sync jeux/likes) + explication reduce + champ console/plateforme

This commit is contained in:
2026-06-26 16:10:02 +02:00
parent 6a99a2d6eb
commit 8a52c92449
+114
View File
@@ -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
<Accueil
jeux={jeux}
setJeux={setJeux}
likes={likes}
setLikes={setLikes} {/* 👈 en plus */}
onLike={liker}
/>
```
### 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.