Les bugs rencontrés sur le slide :
1/ Image manquante
On peut voir dans react-dev-tools que lorsque le state passe à 3, il n'y a pas d'image.
2/ Le mois ne s'affiche pas sur chaque image
3 / L'ordre des éléments dans le slide n'est pas le bon.
Les évènements devraient s'afficher par date en ordre décroissant.
4/ Les bullets ne s'affichent pas en fonction des images
Afin de comprendre le code, il est nécessaire de voir :
Le contexte
Les Hooks
- UseState
- UseEffect
Index
Map
Key
1 / Image manquante
Code initial
const Slider = () => {
const { data } = useData();
const [index, setIndex] = useState(0);
const byDateDesc = data?.focus.sort((evtA, evtB) =>
new Date(evtA.date) < new Date(evtB.date) ? -1 : 1
);
const nextCard = () => {
setTimeout(
() => setIndex(index < byDateDesc.length ? index + 1 : 0),
5000
);
};
useEffect(() => {
nextCard();
});
Code modifié
const Slider = () => {
const { data } = useData();
const [index, setIndex] = useState(0);
const byDateDesc = data?.focus.sort((evtA, evtB) =>
new Date(evtA.date) < new Date(evtB.date) ? -1 : 1
);
const nextCard = () => {
setTimeout(() => {
if (byDateDesc && index < byDateDesc.length - 1) {
setIndex(index + 1);
} else {
setIndex(0);
}
}, 5000);
};
useEffect(() => {
nextCard();
});
Explication du code modifié pour l'image manquante
const Slider = () => {
const { data } = useData();
const [index, setIndex] = useState(0);
const { data } = useData();
Cette ligne extrait la propriété data à partir de l'objet retourné par l'appel à la fonction useData().
useData() est une fonction qui permet d'accéder à certaines données à partir d'un contexte, défini ailleurs dans notre application.
On obtient ainsi l'ensemble des données, et data contient ces données.
const [index, setIndex] = useState(0);
Ici, on utilise le hook useState pour initialiser une variable d'état appelée index avec une valeur initiale de 0.
Cette variable d'état est utilisée pour suivre l'index de l'image actuellement affichée dans votre slider.
setIndex est une fonction que l'on utilise pour mettre à jour la valeur de index ultérieurement.
const nextCard = () => {
setTimeout(() => {
if (byDateDesc && index < byDateDesc.length - 1) {
setIndex(index + 1);
} else {
setIndex(0);
}
}, 5000);
};
const nextCard = () => { ... }
Cette fonction nextCard est appelée pour afficher la prochaine image du slider.
On utilise setTimeout pour retarder l'exécution de cette fonction de 5 secondes, ce qui provoque un défilement automatique des images.
À l'intérieur de la fonction, on vérifie d'abord si byDateDesc est défini (pour éviter les erreurs) et si l'index actuel (index) est inférieur à la longueur du tableau byDateDesc - 1.
Si c'est le cas, on incrémente l'index en utilisant setIndex(index + 1).
Si l'index atteint la fin du tableau, on le remet à zéro pour boucler à travers les images.
useEffect(() => {
nextCard();
});
useEffect(() => { nextCard(); });
On utilise ici le hook useEffect pour exécuter la fonction nextCard après chaque rendu du composant. Cela permet de déclencher le défilement automatique des images.
2/ Le mois ne s'affiche pas sur chaque image
Dans notre code initial, on va chercher les mois avec {getMonth} qui se trouve dans :
.../...//helpers/Date
Seulement dans ce fichier se présente ainsi :
export const MONTHS = {
1: "janvier",
2: "février",
3: "mars",
4: "avril",
5: "mai",
6: "juin",
7: "juillet",
8: "août",
9: "septembre",
10: "octobre",
11: "novembre",
12: "décembre",
};
export const getMonth = (date) => MONTHS[date.getMonth()];
L'erreur dans le code est liée à la manière dont les mois sont indexés.
Dans le code initial, les indices des mois commencent à partir de 1 dans l'objet MONTHS. Par exemple, "janvier" est associé à l'indice 1, "février" à l'indice 2, et ainsi de suite. Cependant, la méthode getMonth() de l'objet Date renvoie des valeurs d'indice de mois allant de 0 à 11, où 0 représente janvier et 11 représente décembre.
Cela signifie que lorsque getMonth() est appelé, on utilise les valeurs de 0 à 11 pour accéder aux noms des mois, mais les noms des mois sont définis avec des indices de 1 à 12. Par conséquent, il y a une erreur.
Code corrigé :
export const MONTHS = [
"janvier",
"février",
"mars",
"avril",
"mai",
"juin",
"juillet",
"août",
"septembre",
"octobre",
"novembre",
"décembre",
];
export const getMonth = (date) => MONTHS[date.getMonth()];
On aurait également pu faire ainsi :
export const MONTHS = {
1: "janvier",
2: "février",
3: "mars",
4: "avril",
5: "mai",
6: "juin",
7: "juillet",
8: "août",
9: "septembre",
10: "octobre",
11: "novembre",
12: "décembre",
};
export const getMonth = (date) => MONTHS[date.getMonth() + 1];
En ajoutant +1 à l'indice retourné par date.getMonth(), on fait correspondre les mois de 0 à 11 renvoyés par getMonth() aux indices de l'objet MONTHS qui commencent à 1 pour janvier.
3 / L'ordre des éléments dans le slide n'est pas le bon
Les évènements devraient s'afficher par date en ordre décroissant.
const byDateDesc = data?.focus.sort((evtA, evtB) =>
new Date(evtA.date) < new Date(evtB.date) ? -1 : 1
);
On compare ici les dates evtA.date et evtB.date, et si evtA.date est inférieur à evtB.date, on renvoie -1, ce qui signifie que evtA précède evtB dans l'ordre de tri.
Cela trie les éléments par ordre croissant de dates.
Code corrigé en inversant evtA et evtB
const byDateDesc = data?.focus.sort((evtB, evtA) =>
new Date(evtA.date) < new Date(evtB.date) ? -1 : 1
);
On peut aussi simplement inverser l'ordre de retour de -1 et 1 dans la fonction de tri, comme ceci :
const byDateDesc = data?.focus.sort((evtA, evtB) =>
new Date(evtA.date) > new Date(evtB.date) ? -1 : 1
);
De cette manière, les éléments seront triés par ordre décroissant de dates.
4/ Les bullets ne s'affichent pas en fonction des images
Plusieurs problèmes se posent.
- J'ai d'abord ajouté une fonction handleBulletClick qui est appelée lors du changement de l'état de la case à cocher (bullet).
Cette fonction met à jour l'index du slide (setIndex) avec l'index du bullet sur lequel on a cliqué.
- Il y avait également un problème de key qui n'était pas unique, ligne 38 :
key={event.title}
Il y a des titres identiques dans les données.
La modification apportée :
key={event.id}
- A la ligne 59,j'ai évalué les conditions de checked des radios bouton en fonction de la valeur du state index.
L'état "checked" de chaque bouton radio est maintenant basé sur la comparaison entre l'index actuel (index) et radioIdx.
Ce qui signifie que le bouton radio correspondant à l'image actuellement affichée est automatiquement coché.
- J'ai également mis un id au focus dans le json et sorti paginationContainer de map.