Afficher des listes
Vous aurez souvent besoin d’afficher des composants similaires à partir d’une collection de données. Vous pouvez utiliser les méthodes des tableaux JavaScript pour manipuler un tableau de données. Dans cette page, vous utiliserez filter()
et map()
avec React pour filtrer et transformer vos données afin de produire un tableau de composants.
Vous allez apprendre
- Comment afficher des composants à partir d’un tableau de données en utilisant le
map()
de JavaScript - Comment n’afficher que certains composants précis en utilisant le
filter()
de JavaScript - Quand et pourquoi utiliser des clés React
Afficher des données à partir de tableaux
Disons que vous avez une liste de contenus.
<ul>
<li>Creola Katherine Johnson : mathématicienne</li>
<li>Mario José Molina-Pasquel Henríquez : chimiste</li>
<li>Mohammad Abdus Salam : physicien</li>
<li>Percy Lavon Julian : chimiste</li>
<li>Subrahmanyan Chandrasekhar : astrophysicien</li>
</ul>
La seule différence entre ces éléments de liste, c’est leur contenu, c’est-à-dire leurs données. Vous aurez souvent besoin d’afficher plusieurs instances d’un même composant mais avec des données différentes lorsque vous construirez des interfaces : listes de commentaires, galeries d’images de profils, etc. Dans de telles situations, vous pourrez stocker les données dans des objets et tableaux JavaScript et utiliser des méthodes comme map()
et filter()
pour produire des listes de composants à partir de ces données.
Voici un court exemple de génération d’une liste d’éléments à partir d’un tableau :
- Déplacez les données dans un tableau
const people = [
'Creola Katherine Johnson : mathématicienne',
'Mario José Molina-Pasquel Henríquez : chimiste',
'Mohammad Abdus Salam : physicien',
'Percy Lavon Julian : chimiste',
'Subrahmanyan Chandrasekhar : astrophysicien',
];
- Transformez les membres de
people
en un nouveau tableau de nœuds JSX,listItems
:
const listItems = people.map(person => <li>{person}</li>);
- Renvoyez
listItems
à partir de votre composant, enrobé dans un<ul>
:
return <ul>{listItems}</ul>;
Voici le résultat :
const people = [ 'Creola Katherine Johnson : mathématicienne', 'Mario José Molina-Pasquel Henríquez : chimiste', 'Mohammad Abdus Salam : physicien', 'Percy Lavon Julian : chimiste', 'Subrahmanyan Chandrasekhar : astrophysicien', ]; export default function List() { const listItems = people.map(person => <li>{person}</li> ); return <ul>{listItems}</ul>; }
Remarquez l’erreur dans la console du bac à sable :
(« Avertissement : chaque enfant d’une liste devrait avoir une prop “key” unique », NdT.)
Vous apprendrez à corriger cette erreur plus loin dans cette page. Avant d’en arriver là, commençons par structurer un peu plus vos données.
Filtrer des tableaux d’éléments
On peut structurer davantage nos données.
const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathématicienne',
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chimiste',
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicien',
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'chimiste',
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicien',
}];
Disons que vous cherchez un moyen de n’afficher que les chimistes. Vous pouvez utiliser la méthode filter()
de JavaScript pour ne renvoyer que ces personnes. Cette méthode s’applique sur un tableau d’éléments, les fait passer à travers un « prédicat » (une fonction qui renvoie true
ou false
au sujet de son argument), et renvoie un nouveau tableau ne contenant que les éléments qui ont satisfait le prédicat (il a renvoyé true
pour ces éléments).
Vous ne vous intéressez qu’aux éléments dont la profession
est 'chimiste'
. Le prédicat correspondant ressemble à (person) => person.profession === 'chimiste'
. Voici comment assembler tout ça :
- Créez un nouveau tableau avec juste les chimistes,
chemists
, en appelantfilter()
surpeople
et en filtrant avecperson.profession === 'chimiste'
:
const chemists = people.filter(person =>
person.profession === 'chimiste'
);
- A présent transformez
chemists
avecmap()
:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
célèbre pour {person.accomplishment}
</p>
</li>
);
- Enfin, renvoyez le
listItems
depuis votre composant :
return <ul>{listItems}</ul>;
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const chemists = people.filter(person => person.profession === 'chimiste' ); const listItems = chemists.map(person => <li> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} célèbre pour {person.accomplishment} </p> </li> ); return <ul>{listItems}</ul>; }
Maintenir l’ordre des éléments de liste avec key
Vous avez pu remarquer dans tous les bacs à sable ci-dessus une erreur dans la console :
(« Avertissement : chaque enfant d’une liste devrait avoir une prop “key” unique », NdT.)
Vous devez fournir à chaque élément de tableau une key
— une chaîne de caractères ou un nombre qui identifie de façon unique cet élément au sein du tableau :
<li key={person.id}>...</li>
Les clés indiquent à React à quel élément du tableau de données correspond chaque élément du tableau de composants, pour qu’il puisse les faire correspondre plus tard. Ça devient important si les éléments de votre tableau sont susceptibles de s’y déplacer (par exemple dans le cadre d’un tri), d’y être insérés ou supprimés. Une key
bien choisie aide React à inférer la nature exacte du changement, et à faire les mises à jour adaptées dans l’arbre DOM.
Plutôt que de générer vos clés à la volée, vous devriez les faire figurer dans vos données :
export const people = [{ id: 0, name: 'Creola Katherine Johnson', profession: 'mathématicienne', accomplishment: 'ses calculs pour vol spatiaux', imageId: 'MK3eW3A' }, { id: 1, name: 'Mario José Molina-Pasquel Henríquez', profession: 'chimiste', accomplishment: 'sa découverte du trou dans la couche d’ozone au-dessus de l’Arctique', imageId: 'mynHUSa' }, { id: 2, name: 'Mohammad Abdus Salam', profession: 'physicien', accomplishment: 'sa théorie de l’électromagnétisme', imageId: 'bE7W1ji' }, { id: 3, name: 'Percy Lavon Julian', profession: 'chimiste', accomplishment: 'ses travaux pionniers sur la cortisone, les stéroïdes et les pilules contraceptives', imageId: 'IOjWm71' }, { id: 4, name: 'Subrahmanyan Chandrasekhar', profession: 'astrophysicien', accomplishment: 'son calcul de la masse des naines blanches', imageId: 'lrWQx8l' }];
En détail
Que faire lorsque chaque élément de la liste doit produire non pas un, mais plusieurs nœuds DOM ?
La syntaxe concise de Fragment <>...</>
ne vous permet pas de passer une clé, vous devez donc soit les regrouper dans une <div>
, soit utiliser la syntaxe plus explicite <Fragment>
, certes un peu plus longue, mais plus explicite :
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
Les Fragments n’impactent pas le DOM, de sorte que ce code produira une liste à plat de <h1>
, <p>
, <h1>
, <p>
, et ainsi de suite.
Où récupérer la key
Selon la source de vos données, vous aurez différentes sources de clés :
- Données issues d’une base de données : si vos données viennent d’une base de données, vous pouvez utiliser les clés / ID de la base, qui sont uniques par nature.
- Données générées localement : si vos données sont générées et persistées localement (ex. une appli de prise de notes), utilisez un compteur incrémentiel,
crypto.randomUUID()
ou un module du styleuuid
en créant vos éléments.
Les règles des clés
- Les clés doivent être uniques dans une même liste. En revanche, vous pouvez avoir les mêmes clés pour des nœuds JSX dans des tableaux distincts.
- Les clés ne doivent pas changer sans quoi elles ne serviraient à rien ! Ne générez pas les clés lors du rendu.
Pourquoi React a-t-il besoin de clés ?
Imaginez que les fichiers sur votre bureau n’aient pas de noms. Vous y feriez alors référence plutôt par leur ordre : le premier fichier, le deuxième, et ainsi de suite. Vous pourriez vous y habituer, sauf que lorsque vous supprimez un fichier, un problème surgit. Le deuxième fichier devient le premier, le troisième devient le deuxième, etc.
Les noms de fichiers dans un dossier et les clés JSX dans un tableau jouent un rôle similaire. Ils nous permettent d’identifier de façon unique un élément parmi ceux qui l’entourent. Une clé bien choisie nous fournit plus d’information que la simple position dans le tableau. Même si la position change en raison d’un réordonnancement, la key
permettra à React d’identifier l’élément tout au long de sa vie.
En résumé
Dans cette page, vous avez appris :
- Comment extraire les données de vos composants pour les placer dans des structures de données comme des tableaux et des objets.
- Comment générer des séries de composants similaires avec le
map()
de JavaScript. - Comment créer des tableaux filtrés d’éléments avec le
filter()
de JavaScript. - Pourquoi et comment utiliser
key
sur chaque composant d’une collection afin que React puisse garder trace de leurs identités même lorsque leurs positions ou les données sous-jacentes changent.
Défi 1 sur 4 · Découper une liste en deux
Cet exemple affiche une liste de personnes.
Modifiez-le pour afficher deux listes distinctes l’une de l’autre : les Chimistes et Tous les autres. Comme précédemment, vous pouvez déterminer si une personne est chimiste en testant person.profession === 'chimiste'
.
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const listItems = people.map(person => <li key={person.id}> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} célèbre pour {person.accomplishment} </p> </li> ); return ( <article> <h1>Scientifiques</h1> <ul>{listItems}</ul> </article> ); }