Contact: correction total likes a la suppression (sync jeux/likes) + explication reduce + champ console/plateforme
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user