Correction services: total de likes recalcule (source de verite = likes par trilogie dans App, total = reduce) au lieu d'un total mute; + fusionner les deux map

This commit is contained in:
2026-06-24 14:47:58 +02:00
parent bd1e9adf13
commit e28c70d440
+101
View File
@@ -0,0 +1,101 @@
# 🔧 Correction — ton total de likes : le **recalculer**, pas le « mâter »
Ton total monte bien quand on clique, mais il y a un souci de fond. Chaque bouton fait ça :
```jsx
// App.jsx
onLike={() => setTotal((t) => t + 1)}
// Carte.jsx
<button onClick={props.onLike}> J'aime</button>
```
Donc chaque clic **ajoute 1 à un compteur `total`** qui vit tout seul dans son coin. Le problème : ce `total` **n'est relié à rien**. Tu ne sais pas combien de likes a **chaque** trilogie, tu ne peux pas « dé-liker », et si tu filtres/retires une carte, le total devient faux. Le total est **inventé par accumulation**, au lieu d'être **calculé à partir des vraies données**.
> 🧠 **Le principe React à retenir :** on garde **une seule source de vérité**, et on **recalcule** le reste à partir d'elle. Ici, la vérité, ce sont **les likes de chaque trilogie**. Le total n'est pas une donnée à part : c'est **la somme** des likes — donc on le **recalcule**, on ne le mute pas.
---
## 🎯 L'idée de la correction
1. La **source de vérité** = un like **par trilogie**, rangé dans le **parent** (`App`).
2. Chaque `Carte` reçoit **son** nombre de likes + une fonction pour **incrémenter le sien**.
3. Le **total** = la **somme** de tous les likes → **recalculé** à chaque affichage.
Comme ça : pas de double comptage, le total est **toujours juste**, et tu pourrais même afficher les likes par carte.
---
## 🪜 Étape par étape
### Étape 1 — ranger les likes dans le parent (un objet `{ id: nombre }`)
```jsx
function App() {
const [likes, setLikes] = useState({}); // ex. { 1: 3, 4: 1 } = 3 likes pour la trilo 1, 1 pour la 4
// incrémente le like d'UNE trilogie précise (par son id)
function liker(id) {
setLikes((prev) => ({ ...prev, [id]: (prev[id] || 0) + 1 }));
}
// ...
}
```
> 🔎 `setLikes((prev) => ({ ...prev, [id]: (prev[id] || 0) + 1 }))` se lit : « recopie tous les likes existants (`...prev`), et remplace **juste** celui de cette `id` par sa valeur + 1 ». Le `(prev[id] || 0)` = « 0 si cette trilo n'a pas encore de like ».
### Étape 2 — recalculer le total (la somme)
```jsx
const total = Object.values(likes).reduce((somme, n) => somme + n, 0);
```
> 🔎 `Object.values(likes)` = la liste des nombres (`[3, 1]`), et `.reduce(...)` les **additionne**. Tu reconnais le `reduce` — ici il **recalcule** le total à chaque rendu, à partir de la vérité. Plus aucun risque qu'il soit faux.
### Étape 3 — donner à chaque carte SON like + sa fonction
```jsx
{filtrees.map((trilo) => (
<Carte
key={trilo.id}
titre={trilo.nom}
niveaux={trilo.niveaux}
likes={likes[trilo.id] || 0} // SON nombre de likes
onLike={() => liker(trilo.id)} // incrémente SON like à elle
/>
))}
```
### Étape 4 — la `Carte` affiche son like et appelle la fonction
```jsx
function Carte(props) {
return (
<div className="carte">
<h2>{props.titre}</h2>
<p>{props.niveaux}</p>
<button onClick={props.onLike}> {props.likes}</button>
</div>
);
}
```
**✅ Test :** chaque carte affiche **son** nombre de likes ; le total en haut = la **somme** et reste juste, quoi qu'il arrive.
---
## 🧹 Pendant que tu y es : tu affiches tes cartes **deux fois**
Dans ton `App.jsx` actuel, il y a **deux** `map` qui créent des `<Carte>` :
- un premier (`trilogies.map`) avec `onLike` mais `nom=...` (pas de `titre`),
- un second (`filtrees.map`) avec `titre`/`niveaux` mais **sans** `onLike`.
Du coup tes trilogies s'affichent en double, et le bouton like n'est pas sur les bonnes cartes. **Garde un seul `map`** : celui sur **`filtrees`** (pour que la recherche marche), et passe-lui **toutes** les props (`titre`, `niveaux`, `likes`, `onLike`). Et dans `Carte`, garde **un seul** `<h2>` (tu as `props.titre` **et** `props.nom` → choisis `titre`).
> 🧭 Rappel : `App` = assembleur. Une seule liste, une seule source de vérité.
---
## ✅ Récap
- [ ] Les likes vivent dans `App`, **par trilogie** (`useState({})`)
- [ ] Une fonction `liker(id)` qui incrémente **une** trilogie
- [ ] Le **total recalculé** avec `Object.values(likes).reduce(...)` (au lieu d'un `total` muté)
- [ ] Chaque `Carte` reçoit `likes={...}` + `onLike={() => liker(id)}`
- [ ] Un **seul** `map` (sur `filtrees`), une `Carte` avec un seul `<h2>`
> 💬 La phrase à garder : **une seule source de vérité, on recalcule le reste.** Un total, un compteur affiché, une moyenne… ça se **dérive** des données, ça ne se stocke pas à part (sinon ça finit par se désynchroniser).