5.4 KiB
🧩 Tuto pas à pas — le parent qui additionne les likes des enfants
Tu cherches à faire remonter les likes : chaque Carte a son compteur, et App (le parent) affiche le total. C'est exactement le bon objectif 👍. Il te manque une seule ligne — et je veux surtout que tu comprennes pourquoi.
🔍 D'abord, pourquoi ton total reste à 0
Regarde le bouton dans ta Carte :
<button onClick={() => setLikes(likes + 1)}>❤️ {likes}</button>
Quand on clique, tu fais setLikes(likes + 1) → ça met à jour le compteur de la carte. ✅
Mais… tu n'as jamais prévenu le parent ! La fonction onLike que App t'a donnée en prop n'est jamais appelée. Donc App ne sait pas qu'on a liké → total reste à 0.
🧠 L'idée à comprendre : un enfant ne peut pas modifier directement l'état du parent. Le parent lui prête une fonction (
onLike), et l'enfant doit l'appeler au bon moment. C'est l'enfant qui dit « hé, on m'a likée ! » — le parent décide quoi en faire.
🪜 La correction, étape par étape
Étape 1 — le parent a déjà tout (rien à changer)
Dans App.jsx, tu as déjà :
const [total, setTotal] = useState(0);
// ...
<Carte ... onLike={() => setTotal((t) => t + 1)} />
// ...
<p>Total de likes : {total}</p>
Le parent tient le total et passe une fonction onLike à chaque carte. ✅
Étape 2 — l'enfant doit APPELER onLike (la ligne qui manque)
Dans Carte, le bouton doit faire deux choses au clic : augmenter son compteur et prévenir le parent.
<button
onClick={() => {
setLikes(likes + 1); // 1) j'augmente MON compteur (état de la carte)
props.onLike(); // 2) je préviens le PARENT (sa fonction)
}}
>
❤️ {likes}
</button>
🔎 Deux instructions dans le
onClick→ on les met entre accolades{ ... }avec un;entre les deux. C'est une petite fonction qui fait deux choses à la suite.
✅ Test : clique sur le ❤️ d'une carte → son compteur monte et le « Total de likes » en haut monte aussi. Clique sur une autre carte → le total continue de grimper.
🎓 Ta question : pourquoi chaque bouton démarre avec la même valeur ?
C'est une excellente question, et la réponse, c'est l'initialisation de useState.
const [likes, setLikes] = useState(
() => Number(localStorage.getItem("likes-" + props.id)) || 0
);
1. La valeur dans useState(...) n'est qu'un point de départ
L'argument que tu passes à useState(...) est la valeur initiale : React l'utilise une seule fois, au tout premier affichage de la carte, pour démarrer le compteur. Ensuite, c'est setLikes(...) qui prend le relais — l'initialisation ne sert plus.
🧠
useState(valeurDeDépart)= « démarre à cette valeur, la première fois seulement ». Après, l'état vit sa vie.
2. Chaque <Carte> est indépendante (elle ne partage rien)
Chaque fois que tu écris <Carte />, React crée une instance séparée, avec son propre likes. Liker la carte n°1 ne touche pas la carte n°2 : ce sont des compteurs distincts.
3. Alors pourquoi elles affichent toutes la même valeur au départ ?
Parce qu'elles exécutent toutes le même calcul d'initialisation, et qu'au premier lancement, localStorage est vide :
localStorage.getItem("likes-" + props.id)→ renvoienull(rien n'est encore stocké)Number(null)→0, donc|| 0→ 0
→ toutes les cartes démarrent à 0. Ce n'est pas qu'elles « partagent » une valeur : c'est qu'elles partent toutes de la même situation (rien en mémoire). C'est comme 4 personnes qui commencent un jeu : elles ont toutes 0 point au début, mais chacune marque ses propres points ensuite.
💡 La preuve que c'est bien indépendant et par-carte : like la carte n°1, recharge la page (F5). La carte n°1 retrouve sa valeur (lue dans
localStorageà la clélikes-1), les autres restent à 0. Chaque carte a donc bien sa propre initialisation, basée sur sonid.
⚠️ Un piège que tu as déjà senti (commit « buggy »)
Tu as remarqué : les likes par carte survivent au rechargement (ils sont dans localStorage), mais le total repart à 0 après un F5. Normal : le total du parent n'est pas stocké, et il n'est pas recalculé à partir des cartes — il ne fait que s'incrémenter aux clics.
Pour l'instant, c'est OK : ton objectif était de faire remonter un like vers le parent (le pattern callback ci-dessus), et c'est réussi.
🔭 Pour aller plus loin (plus tard) : il existe une version plus robuste où le total se recalcule tout seul à partir des likes (une seule « source de vérité »). On en reparlera — c'est l'étape d'après.
🧹 Petit nettoyage
Dans Carte, tu as un effet vide qui ne sert à rien :
useEffect(() => {}, [likes]); // ❌ à supprimer
Enlève-le, il ne fait rien.
✅ Récap
- Le parent prête une fonction (
onLike) ; l'enfant doit l'appeler → c'est la ligneprops.onLike()qui te manquait. - Au clic : l'enfant met à jour son état et appelle
props.onLike(). useState(x)= valeur de départ, utilisée une fois. Chaque carte est indépendante ; elles démarrent toutes pareil parce qu'au premier lancement la mémoire est vide (toutes à 0).- Supprime le
useEffectvide.