Aller au contenu principal

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...

  1. avec le tableau reponses de la séance précédente, afficher le texte de la dernière réponse avec at(-1)
  2. avec find, retrouver la réponse dont l'id vaut 12 et afficher son texte
  3. dire comment tester qu'un tableau nommé liste est 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.

Bonne pratique - Règle d'or de React

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).

Le spread fait une copie « superficielle »

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​


Que contient la variable niveau après : const { niveau } = { id: 1, niveau: 3 }; ?


Que contient b après : const [a, b] = ["x", "y", "z"]; ?


Quelle expression crée un NOUVEAU tableau contenant les éléments de liste plus "D" à la fin ?


Que vaut joueur2 après : const joueur2 = { ...joueur, score: 11 }; (joueur vaut { pseudo: "Alice", score: 10 }) ?


Pourquoi React préfère-t-il qu'on crée un nouveau tableau plutôt que d'utiliser push ?



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.


Bonne pratique - Extraire uniquement ce dont on a besoin

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).


Bonne pratique - Valeur par défaut dans les paramètres

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é.


Bonne pratique - Fonction pure et immuable

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.


Bonne pratique - La dernière valeur gagne

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​

NotionRésumé
Destructuration d'objetconst { a, b } = objet; extrait des propriétés par leur nom.
Destructuration de tableauconst [x, y] = tableau; extrait des éléments par leur position.
Paramètres destructurésfunction 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'orNe pas modifier l'existant : créer une nouvelle valeur (indispensable avec React).
Copie superficielleLe 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.