Affichage conditionnel
Vos composants devront souvent produire des affichages distincts en fonction de certaines conditions. Dans React, vous pouvez produire du JSX conditionnellement en utilisant des syntaxes JavaScript telles que les instructions if
et les opérateurs &&
et ? :
.
Vous allez apprendre
- Comment renvoyer du JSX différent en fonction d’une condition
- Comment inclure ou exclure conditionnellement un bout de JSX
- Les raccourcis syntaxiques habituels que vous rencontrerez dans les bases de code utilisant React
Renvoi conditionnel de JSX
Disons que vous avez un composant PackingList
qui affiche plusieurs Item
s que vous pouvez marquer comme placés ou non dans les bagages :
Error
Extra 185 of 186 byte(s) found at buffer[1]
Remarquez que certains composants Item
ont leur prop isPacked
à true
plutôt qu’à false
. Vous souhaitez ajouter une coche (✅) aux objets pour lesquels isPacked={true}
.
Vous pourriez écrire ça sous forme d’instruction if
/else
, comme ceci :
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
Si la prop isPacked
vaut true
, ce code renverra un arbre JSX différent. Suite à cette modification, certains des éléments auront une coche à la fin :
function Item({ name, isPacked }) { if (isPacked) { return <li className="item">{name} ✅</li>; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Liste d’affaires de Sally Ride</h1> <ul> <Item isPacked={true} name="Combinaison spatiale" /> <Item isPacked={true} name="Casque à feuille d’or" /> <Item isPacked={false} name="Photo de Tam" /> </ul> </section> ); }
Error
Extra 185 of 186 byte(s) found at buffer[1]
Essayez de modifier le balisage renvoyé dans chaque cas, et voyez comme le résultat évolue !
Notez que vous avez créé des branches logiques en utilisant les instructions if
et else
de JavaScript. Dans React, le flux de contrôle (tel que les conditions) est géré par JavaScript.
Conditionnellement ne rien renvoyer avec null
Dans certains cas, vous ne voudrez rien renvoyer du tout. Disons par exemple que vous ne souhaitez pas afficher les objets déjà mis dans les bagages. Un composant doit pourtant bien renvoyer quelque chose. Dans un tel cas, vous pouvez renvoyer null
:
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
Si isPacked
est à true
, le composant ne renverra rien, donc null
. Autrement, il renverra le JSX à afficher.
function Item({ name, isPacked }) { if (isPacked) { return null; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Liste d’affaires de Sally Ride</h1> <ul> <Item isPacked={true} name="Combinaison spatiale" /> <Item isPacked={true} name="Casque à feuille d’or" /> <Item isPacked={false} name="Photo de Tam" /> </ul> </section> ); }
En pratique, les composants ne renvoient pas souvent null
parce que ça peut surprendre le développeur qui essaierait de l’afficher. Vous préférerez généralement inclure ou exclure le composant dans le JSX du composant parent. Voici comment faire ça !
Inclure du JSX conditionnellement
Dans l’exemple précédent, vous contrôliez quel arbre JSX renvoyer (si tant est qu’il y en ait un !) depuis le composant. Vous avez peut-être remarqué une légère duplication dans l’affichage produit. Ce JSX :
<li className="item">{name} ✅</li>
est très similaire à
<li className="item">{name}</li>
Les deux branches conditionnelles renvoient <li className="item">...</li>
:
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
Même si cette duplication n’est pas dangereuse, elle complexifie la maintenance de votre code. Et si vous vouliez changer le className
? Vous devriez le mettre à jour à deux endroits de votre code ! Dans un tel cas, vous pourriez plutôt inclure un bout de JSX de façon conditionnelle pour rendre votre code plus DRY.
Opérateur (ternaire) conditionnel (? :
)
JavaScript dispose d’une syntaxe compacte pour écrire une expression conditionnelle : l’opérateur conditionnel, également appelé « ternaire » :
Au lieu de ceci :
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
Vous pouvez plutôt écrire ceci :
return (
<li className="item">
{isPacked ? name + ' ✅' : name}
</li>
);
Vous pouvez le lire comme suit : « si isPacked
est vrai, alors (?
) affiche name + ' ✅'
, sinon (:
) affiche name
».
En détail
Si vous êtes habitué·e à la programmation orientée objet, vous vous dites peut-être que les deux exemples ci-dessus sont subtilement différents parce que l’un d’eux pourrait créer deux « instances » de <li>
. mais les éléments JSX ne sont pas des « instances » car ils ne contiennent aucun état interne et ne sont pas de véritables nœuds DOM. Il s’agit de descriptifs légers, comme des plans de construction. De sorte que ces deux exemples sont effectivement parfaitement équivalents. La page Préserver et réinitialiser l’état explore en détail ces aspects.
Disons maintenant que vous souhaitez enrober le texte d’un objet mis en bagages par une autre balise HTML, telle que <del>
, pour le biffer. Vous pouvez ajouter des sauts de lignes et des parenthèses, pour qu’il soit plus facile d’imbriquer davantage de JSX dans chacun des cas :
function Item({ name, isPacked }) { return ( <li className="item"> {isPacked ? ( <del> {name + ' ✅'} </del> ) : ( name )} </li> ); } export default function PackingList() { return ( <section> <h1>Liste d’affaires de Sally Ride</h1> <ul> <Item isPacked={true} name="Combinaison spatiale" /> <Item isPacked={true} name="Casque à feuille d’or" /> <Item isPacked={false} name="Photo de Tam" /> </ul> </section> ); }
Ce style fonctionne bien pour des conditions simples, mais utilisez-le avec modération. Si vos composants deviennent difficiles à lire en raison de trop de balisages conditionnels imbriqués, envisagez d’extraire des composants enfants pour nettoyer tout ça. Dans React, le balisage fait partie de votre code, vous pouvez donc recourir à des variables et des fonctions pour nettoyer les expressions complexes.
L’opérateur logique ET (&&
)
Un autre raccourci que vous rencontrerez souvent utilise l’opérateur ET logique (&&
) de JavaScript. Dans les composants React, il apparaît souvent lorsque vous souhaitez afficher du JSX lorsqu’une condition est remplie, ou ne rien afficher dans le cas contraire. Avec &&
, vous pouvez afficher conditionnellement la coche seulement si isPacked
vaut true
:
return (
<li className="item">
{name} {isPacked && '✅'}
</li>
);
Vous pouvez le lire comme suit : « si isPacked
est vrai, alors (&&
) affiche la coche, sinon n’affiche rien ».
Le voici en action :
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Liste d’affaires de Sally Ride</h1> <ul> <Item isPacked={true} name="Combinaison spatiale" /> <Item isPacked={true} name="Casque à feuille d’or" /> <Item isPacked={false} name="Photo de Tam" /> </ul> </section> ); }
Une expression &&
JavaScript renvoie la valeur de son opérande à droite (dans notre cas, la coche) si l’opérande à gauche (notre condition) vaut true
. Mais si la condition vaut false
, React considèrera false
comme un « trou » dans l’arbre JSX, tout comme null
ou undefined
, et n’affichera rien à cet endroit.
Affecter conditionnellement du JSX à une variable
Lorsque les raccourcis rendent votre code compliqué à lire, essayez d’utiliser plutôt une instruction if
et une variable. Vous pouvez réaffecter les variables déclarées avec let
, alors commencez par le contenu que vous souhaiteriez afficher par défaut, comme le nom :
let itemContent = name;
Utilisez une instruction if
pour réaffecter une expression JSX à itemContent
si isPacked
vaut true
:
if (isPacked) {
itemContent = name + " ✅";
}
Les accolades « ouvrent une fenêtre » vers JavaScript. Incorporez la variable entre accolades dans l’arbre JSX renvoyé, ce qui y imbriquera l’expression précédemment calculée :
<li className="item">
{itemContent}
</li>
Ce style est certes le plus verbeux, mais au final le plus flexible. Le voici en action :
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = name + " ✅"; } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Liste d’affaires de Sally Ride</h1> <ul> <Item isPacked={true} name="Combinaison spatiale" /> <Item isPacked={true} name="Casque à feuille d’or" /> <Item isPacked={false} name="Photo de Tam" /> </ul> </section> ); }
Comme précédemment, ça ne marche pas seulement pour le texte, mais pour n’importe quel JSX aussi :
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = ( <del> {name + " ✅"} </del> ); } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Liste d’affaires de Sally Ride</h1> <ul> <Item isPacked={true} name="Combinaison spatiale" /> <Item isPacked={true} name="Casque à feuille d’or" /> <Item isPacked={false} name="Photo de Tam" /> </ul> </section> ); }
Si vous n’êtes pas à l’aise avec JavaScript, cette variété de styles peut vous sembler intimidante au premier abord. Ceci dit, apprendre ces différents styles vous aidera à lire et écrire n’importe quel code JavaScript — pas seulement des composants React ! Choisissez le style que vous préférez pour commencer, puis revenez sur cette page si vous oubliez quels autres styles marchent aussi.
En résumé
- Dans React, vous contrôlez les branches logiques avec JavaScript.
- Vous pouvez renvoyer une expression JavaScript conditionnellement avec une instruction
if
. - Vous pouvez sauver conditionnellement du JSX dans une variable puis l’inclure dans un autre bout de JSX grâce aux accolades.
- En JSX,
{cond ? <A /> : <B />}
signifie « sicond
, affiche<A />
, sinon<B />
». - En JSX,
{cond && <A />}
signifie « sicond
, affiche<A />
, sinon rien ». - Les raccourcis sont fréquents, mais vous n’êtes pas obligé·e de les utiliser si vous préférez de simples
if
.
Défi 1 sur 3 · Afficher un icône pour les objets non traités avec ? :
Utilisez l’opérateur conditionnel (cond ? a : b
) pour afficher ❌ si isPacked
ne vaut pas true
.
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Liste d’affaires de Sally Ride</h1> <ul> <Item isPacked={true} name="Combinaison spatiale" /> <Item isPacked={true} name="Casque à feuille d’or" /> <Item isPacked={false} name="Photo de Tam" /> </ul> </section> ); }