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:
@@ -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).
|
||||
Reference in New Issue
Block a user