Passer des props à un composant
Les composants React utilisent des props pour communiquer entre eux. Chaque composant parent peut passer des informations à ses composants enfants en leur donnant des props. Les props vous rappellent peut-être les attributs HTML, mais vous pouvez y passer n’importe quelle valeur JavaScript, y compris des objets et des fonctions.
Vous allez apprendre
- Comment passer des props à un composant
- Comment lire les props au sein d’un composant
- Comment spécifier des valeurs par défaut pour les props
- Comment passer du JSX à un composant
- Comment les props peuvent changer au fil du temps
Props standardisées
Les props sont des informations que vous passez à une balise JSX. Par exemple, une balise <img>
compte parmi ses props className
, src
, alt
, width
et height
:
function Avatar() { return ( <img className="avatar" src="https://i.imgur.com/1bX5QH6.jpg" alt="Lin Lanying" width={100} height={100} /> ); } export default function Profile() { return ( <Avatar /> ); }
Les props que vous pouvez passer à une balise <img>
sont bien définies (ReactDOM respecte le standard HTML). Mais vous pouvez passer les props de votre choix à vos propres composants, tels qu’<Avatar>
, pour les personnaliser. Voici comment faire !
Passer des props à un composant
Dans le code qui suit, le composant Profile
ne passe aucune prop à son composant fils, Avatar
:
export default function Profile() {
return (
<Avatar />
);
}
Vous pouvez donner quelques props à Avatar
en deux étapes.
Étape 1 : passez des props au composant enfant
Commencez par passer quelques props à Avatar
. Par exemple, passons deux props : person
(un objet) et size
(un nombre) :
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
Vous pouvez maintenant lire ces props au sein du composant Avatar
.
Étape 2 : lisez les props dans le composant enfant
Vous pouvez lire ces props en listant leurs noms person, size
séparés par des virgules entre ({
et })
immédiatement après function Avatar
. Ça vous permet de les utiliser dans le code d’Avatar
, comme si vous aviez une variable locale.
function Avatar({ person, size }) {
// person et size sont disponibles ici
}
Ajoutez un peu de logique à Avatar
qui se base sur les props person
et size
pour le rendu, et vous y serez !
Vous pouvez désormais configurer Avatar
pour s’afficher de différentes façons selon les valeurs de ses props. Essayez de jouer avec ces valeurs !
import { getImageUrl } from './utils.js'; function Avatar({ person, size }) { return ( <img className="avatar" src={getImageUrl(person)} alt={person.name} width={size} height={size} /> ); } export default function Profile() { return ( <div> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> <Avatar size={80} person={{ name: 'Aklilu Lemma', imageId: 'OKS67lh' }} /> <Avatar size={50} person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} /> </div> ); }
Les props vous permettent de réfléchir aux composants parent et enfant indépendamment. Par exemple, vous pouvez modifier les props person
et size
au sein de Profile
sans avoir à vous préoccuper de comment Avatar
les utilise. De la même façon, vous pouvez modifier l’utilisation interne de ces props par Avatar
sans vous préoccuper de Profile
.
Vous pouvez concevoir les props comme des « molettes » que vous pouvez ajuster. Elles jouent le même rôle que les arguments des fonctions — en fait, les props sont le seul argument de votre composant ! Les fonctions composants React ne prennent qu’un argument, qui est l’objet props
:
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
Le plus souvent vous n’aurez pas besoin de l’objet props
lui-même dans son intégralité, vous le déstructurerez donc en props individuelles.
Spécifier une valeur par défaut pour une prop
Si vous souhaitez donner une valeur par défaut à une prop pour qu’elle l’exploite lorsque le composant parent ne fournit pas de valeur, vous pouvez le faire dans la déstructuration en ajoutant =
suivi de la valeur par défaut, juste après le nom de la prop :
function Avatar({ person, size = 100 }) {
// ...
}
À présent, si <Avatar person={...} />
est utilisé sans prop size
, la size
sera définie à 100
.
La valeur par défaut n’est utilisée que si la prop size
est manquante ou que vous passez size={undefined}
. Mais si vous passez size={null}
ou size={0}
, la valeur par défaut ne sera pas utilisée.
Transmettre des props avec la syntaxe de spread JSX
Il peut arriver que passer des props soit très répétitif :
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
Un tel code répétitif n’est pas problématique en soi — il peut même être plus lisible. Mais vous pourriez préférer la concision. Certains composants refilent toutes leurs props à leurs enfants, comme ce Profile
le fait avec Avatar
. Dans la mesure où ils n’utilisent pas leurs props directement, il peut être pertinent de recourir à la syntaxe de spread, nettement plus concise :
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
Ça transmet toutes les props de Profile
à Avatar
sans avoir à les lister chacune par leur nom.
Utilisez la syntaxe de spread avec discernement. Si vous l’utilisez dans de nombreux composants, c’est que quelque chose ne va pas. Le plus souvent, c’est un signe que vous devriez découper vos composants et passer du JSX enfant. On va voir comment tout de suite !
Passer du JSX comme enfant
On imbrique fréquemment les balises natives du navigateur :
<div>
<img />
</div>
Vous voudrez parfois faire de même avec vos propres composants :
<Card>
<Avatar />
</Card>
Lorsque vous imbriquez du contenu dans une balise JSX, le composant parent reçoit ce contenu sous forme d’une prop appelée children
. Par exemple, le composant Card
ci-dessous recevra une prop children
qui vaudra <Avatar />
et l’affichera dans une div d’enrobage :
import Avatar from './Avatar.js'; function Card({ children }) { return ( <div className="card"> {children} </div> ); } export default function Profile() { return ( <Card> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> </Card> ); }
Tentez de remplacer le <Avatar>
au sein de <Card>
avec du texte pour constater que le composant Card
peut enrober n’importe quel contenu imbriqué. Il n’a pas besoin de « savoir » ce qui est affiché à l’intérieur de lui. Vous retrouverez cette approche flexible dans de nombreux endroits.
Voyez la prop children
d’un composant comme une sorte de « trou » qui peut être « rempli » par les composants parents avec du JSX quelconque. Vous utiliserez souvent la prop children
pour des enrobages visuels : panneaux, grilles, etc.
Illustré par Rachel Lee Nabors
Les props changent avec le temps
Le composant Clock
ci-dessous reçoit deux props de son composant parent : color
et time
. (Le code du composant parent est laissé de côté parce qu’il utilise un état, concept que nous n’avons pas encore exploré.)
Essayez de modifier la couleur dans la liste déroulante :
export default function Clock({ color, time }) { return ( <h1 style={{ color: color }}> {time} </h1> ); }
Cet exemple illustre le fait qu’un composant peut recevoir des props différentes au fil du temps. Les props ne sont pas toujours figées ! Ici la prop time
change à chaque seconde, et la prop color
change lorsque vous sélectionnez une autre couleur. Les props reflètent les données du composant à un instant donné, plutôt que seulement leurs valeurs au démarrage.
Cependant, les props sont immuables — un terme qui en informatique signifie « non modifiable ». Lorsqu’un composant a besoin de changer ses props (par exemple, en réponse à une interaction utilisateur ou à de nouvelles données), il doit « demander » à son composant parent de lui passer des props différentes — et donc un nouvel objet ! Ses anciennes props seront alors mises au rebut, et le moteur JavaScript récupèrera à terme la mémoire qui leur était associée.
N’essayez pas de « changer les props ». Lorsque vous aurez besoin de réagir à une interaction utilisateur (telle qu’un changement de la couleur sélectionnée), vous devrez « mettre à jour l’état », ce que vous apprendrez à faire dans L’état : la mémoire d’un composant.
En résumé
- Pour passer des props, ajoutez-les au JSX, comme pour des attributs HTML.
- Pour lire des props, utilisez une déstructuration comme dans
function Avatar({ person, size })
. - Vous pouvez spécifier une valeur par défaut comme
size = 100
, qui sera utilisée si la prop est manquante ou vautundefined
. - Vous pouvez transmettre tous les props avec la syntaxe de spread JSX
<Avatar {...props} />
, mais n’en abusez pas ! - Le JSX imbriqué dans votre composant, comme dans
<Card><Avatar /></Card>
est fourni via la propchildren
du composantCard
. - Les props sont des instantanés en lecture seule : chaque rendu reçoit une nouvelle version des props.
- Ne modifiez pas les props. Si vous avez besoin d’interactivité, utilisez l’état.
Défi 1 sur 3 · Extraire un composant
Ce composant Gallery
contient un balisage très similaire pour deux profils. Extrayez-en un composant Profile
pour réduire la duplication. Vous devrez choisir quelles props lui passer.
import { getImageUrl } from './utils.js'; export default function Gallery() { return ( <div> <h1>Scientifiques remarquables</h1> <section className="profile"> <h2>Maria Skłodowska-Curie</h2> <img className="avatar" src={getImageUrl('szV5sdG')} alt="Maria Skłodowska-Curie" width={70} height={70} /> <ul> <li> <b>Profession : </b> physicienne et chimiste </li> <li> <b>Récompenses : 4 </b> (Prix Nobel de Physique, Prix Nobel de Chimie, Médaille Davy, Médaille Matteucci) </li> <li> <b>A découvert : </b> le Polonium (élément) </li> </ul> </section> <section className="profile"> <h2>Katsuko Saruhashi</h2> <img className="avatar" src={getImageUrl('YfeOqp2')} alt="Katsuko Saruhashi" width={70} height={70} /> <ul> <li> <b>Profession : </b> géochimiste </li> <li> <b>Récompenses : 2 </b> (Prix Miyake de géochimie, Prix Tanaka) </li> <li> <b>A découvert : </b> une méthode de mesure du dioxyde de carbone dans l’eau de mer </li> </ul> </section> </div> ); }