Destructuration et spread
Extraire des valeurs en une ligne, et copier plutôt que modifier : les deux gestes les plus utilisés dans un composant React.
Objectifs de la séance
- extraire des propriétés d'un objet (destructuration d'objet) ;
- extraire des éléments d'un tableau (destructuration de tableau) ;
- utiliser la destructuration dans les paramètres d'une fonction ;
- copier un tableau ou un objet avec l'opérateur spread
...; - comprendre pourquoi on crée une copie plutôt que de modifier l'original.
Petite vérification
Avant de commencer, vérifiez si vous savez...
- avec le tableau
reponsesde la séance précédente, afficher le texte de la dernière réponse avecat(-1) - avec
find, retrouver la réponse dont l'idvaut12et afficher son texte - dire comment tester qu'un tableau nommé
listeest vide
📌 Réponse attendue
Notions théoriques
Destructurer un objet
Au lieu de répéter question.enonce, question.niveau..., la destructuration extrait plusieurs propriétés en une seule ligne.
const question = { id: 1, enonce: "Qu'est-ce que le phishing ?", niveau: 2 };
// Sans destructuration
const enonce1 = question.enonce;
const niveau1 = question.niveau;
// Avec destructuration
const { enonce, niveau } = question;
console.log(enonce); // Qu'est-ce que le phishing ?
console.log(niveau); // 2
Les accolades à gauche du = signifient : « crée une variable pour chacun de ces noms, avec la valeur de la propriété correspondante ».
Variantes utiles :
// Renommer
const { enonce: titre } = question;
console.log(titre);
// Valeur par défaut si la propriété est absente (undefined)
const { indice = "Aucun indice" } = question;
console.log(indice); // Aucun indice
Destructurer un tableau
Pour un tableau, on utilise des crochets : l'ordre compte, pas les noms.
const themes = ["mots de passe", "hameçonnage", "réseaux"];
const [premier, deuxieme] = themes;
console.log(premier); // mots de passe
console.log(deuxieme); // hameçonnage
Vous croiserez cette écriture dans chaque composant React :
const [score, setScore] = useState(0); // aperçu de la partie 7
useState renvoie un tableau de deux éléments ; on les nomme directement score et setScore.
Destructurer dans les paramètres d'une fonction
C'est l'usage le plus courant : une fonction qui reçoit un objet extrait directement ce dont elle a besoin.
// Sans destructuration
function afficherQuestion(question) {
console.log(`${question.enonce} (niveau ${question.niveau})`);
}
// Avec destructuration : on voit tout de suite les données utilisées
function afficherQuestion2({ enonce, niveau = 1 }) {
console.log(`${enonce} (niveau ${niveau})`);
}
afficherQuestion2({ enonce: "Qu'est-ce qu'un VPN ?" });
// Qu'est-ce qu'un VPN ? (niveau 1)
Les composants Expo reçoivent leurs données de cette façon : function CarteQuestion({ enonce, niveau }) { ... }.
Le spread ... : copier un tableau ou un objet
L'opérateur spread (« étaler ») ... recopie le contenu d'un tableau ou d'un objet dans un nouveau.
const themes = ["mots de passe", "hameçonnage"];
const copie = [...themes]; // copie du tableau
const plus = [...themes, "réseaux"]; // copie + un élément ajouté à la fin
const debut = ["accueil", ...themes]; // un élément ajouté au début
console.log(themes); // [ 'mots de passe', 'hameçonnage' ] (inchangé)
console.log(plus); // [ 'mots de passe', 'hameçonnage', 'réseaux' ]
Pour les objets, on copie puis on remplace une ou plusieurs propriétés (la dernière valeur écrite l'emporte) :
const joueur = { pseudo: "Alice", score: 10, niveau: 1 };
const joueurSuivant = { ...joueur, score: 11 };
console.log(joueur); // { pseudo: 'Alice', score: 10, niveau: 1 } (inchangé)
console.log(joueurSuivant); // { pseudo: 'Alice', score: 11, niveau: 1 }
Pourquoi copier plutôt que modifier ?
Comparez deux façons d'ajouter une réponse :
const reponses = ["A", "B"];
// 1. Modifier l'original
reponses.push("C");
// 2. Créer un nouveau tableau
const nouvelles = [...reponses, "D"];
Dans React, l'écran se met à jour quand il détecte que la donnée a changé, et il le détecte en comparant l'ancien et le nouveau tableau. Si vous modifiez le tableau en place, l'ancien et le nouveau sont le même objet : React ne voit aucune différence et l'écran ne bouge pas.
Ne modifiez jamais un tableau ou un objet existant : créez-en un nouveau. Cette règle évite aussi des bugs difficiles à trouver (une donnée qui change « en cachette » à un endroit du programme alors qu'une autre partie s'en servait).
Seul le premier niveau est copié. Les objets contenus à l'intérieur restent partagés entre l'original et la copie. Pour changer une propriété imbriquée, il faut aussi copier le niveau intermédiaire :
const joueur = { pseudo: "Alice", stats: { score: 10 } };
const suivant = { ...joueur, stats: { ...joueur.stats, score: 11 } };
Le reste ... : regrouper
Le même symbole ... sert aussi à regrouper le reste des valeurs dans une destructuration ou dans les paramètres d'une fonction.
const [premier, ...autres] = ["A", "B", "C"];
console.log(autres); // [ 'B', 'C' ]
const { id, ...sansId } = { id: 1, enonce: "Question", niveau: 2 };
console.log(sansId); // { enonce: 'Question', niveau: 2 }
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Votre mission : mettre à jour les données du quiz sans jamais les modifier en place. Travaillez dans le fichier labo-js/spread.js.
Étape 1 — Destructurer une question
Extrayez enonce et niveau de la question en une seule ligne.
Ne destructurez que les propriétés réellement utilisées (ici enonce et niveau, pas id). Le lecteur voit immédiatement de quelles données dépend le code.
Étape 2 — Destructurer les paramètres d'une fonction
Écrivez decrireQuestion qui reçoit un objet et utilise directement enonce et niveau (avec la valeur 1 par défaut pour niveau).
Une valeur par défaut dans la destructuration rend la fonction tolérante : un objet incomplet ne provoque plus d'affichage « undefined ».
Étape 3 — Ajouter à un tableau sans le modifier
Écrivez ajouterReponse(reponses, nouvelle) qui renvoie un nouveau tableau, et vérifiez que l'original n'a pas changé.
ajouterReponse ne modifie pas son argument et renvoie toujours le même résultat pour les mêmes entrées : c'est une fonction pure. C'est exactement la forme que prendront vos mises à jour d'état dans React.
Étape 4 — Mettre à jour un objet sans le modifier
Écrivez gagnerUnPoint(joueur) qui renvoie un nouvel objet avec un score augmenté de 1.
Dans { ...joueur, score: 11 }, score est écrit après le spread : il écrase la valeur copiée. Si vous écriviez { score: 11, ...joueur }, la valeur d'origine reviendrait. L'ordre compte !
📌 Une solution
Ce qu'il faut retenir
| Notion | Résumé |
|---|---|
| Destructuration d'objet | const { a, b } = objet; extrait des propriétés par leur nom. |
| Destructuration de tableau | const [x, y] = tableau; extrait des éléments par leur position. |
| Paramètres destructurés | function f({ a, b = 1 }) { ... } : on voit tout de suite les données utilisées. |
Spread ... | [...liste, x] et { ...objet, cle: valeur } créent des copies modifiées. |
| Règle d'or | Ne pas modifier l'existant : créer une nouvelle valeur (indispensable avec React). |
| Copie superficielle | Le spread ne copie que le premier niveau. |
Aperçu de la prochaine séance
Vous savez copier et extraire. Dans la prochaine séance, vous découvrirez map, filter, reduce et sort : les méthodes qui
transforment une liste entière en une seule ligne, sans boucle for. C'est le moyen d'afficher une liste d'éléments dans Expo.