Seance4 1 Cours
Seance4 1 Cours
Seance4 1 Cours
4. Le langage JSX
Les concepteurs de React ont donc cherché un moyen d’alléger l’écriture et leur choix
s’est porté sur l’utilisation de JSX (JavaScript eXtension). JSX est une forme d’écriture
des éléments React, plus simple à lire et à écrire que les instructions
React.createElement(). Cette syntaxe est donc abondamment utilisée dans les
programmes React.
Au fur et à mesure, vous verrez que le JSX est un langage très intuitif à utiliser. Voici les
deux propriétés de base pour ce qui est des balises utilisées :
Toute balise commençant par une minuscule (div, span, label, etc.) est réservé
aux éléments HTML. Ces éléments sont déclarés par React DOM, et vous
obtiendrez une erreur si vous utilisez un élément inexistant.
Toute balise commençant par une majuscule (Greetings, App, etc.) doit être
déclarée explicitement, ce doit donc être un élément du scope courant :
fonction déjà déclarée, composant importé d’une bibliothèque ou d’un autre
fichier…
Pour afficher ce paragraphe, on utilise l’outil Babel pour interpréter le code JSX et de
le transformer en interne en code JavaScript compréhensible par le navigateur.
D’autres outils existent, nous utiliserons celui-ci.
La page HTML utilisant Babel s’écrit de la façon suivante, en intégrant notre code JSX.
Fichier index.html utilisant Babel afin d’interpréter le code JSX.
<html>
<head>
<script
src="https://unpkg.com/react@16/umd/react.development.js"
crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-
dom.development.js" crossorigin></script>
<script
src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="app"></div>
</body>
<script type="text/babel">
var p = <p>Hello React</p>; // Code JSX
console.log(p); // Affichage dans la console de l’élément
React
ReactDOM.render(p, document.getElementById("app"));
</script>
</html>
On inclut le fichier JavaScript de Babel au moyen de la balise <script src="..."> (cela
cor- respond à l’interpréteur qui traduira le code JSX en code JavaScript), puis on
indique quelle partie du code JavaScript est à interpréter par Babel. Pour cela, on inclut
l’attribut type="text/babel" dans la balise <script> contenant notre code JavaScript
(et JSX).
Babel
ES6 + JavaScript
ES6 React
Le code JavaScript permettant la création des éléments React est écrit en JSX (et sera
traduit en JavaScript pur par Babel), tandis que les éléments React ainsi créés seront
insérés dans la page HTML au moyen de l’instruction ReactDOM.render().
L’affichage correspond au paragraphe contenant "Hello React", tandis que l’onglet
React de la fenêtre des outils de développement montre l’élément React créé suite à
la transformation du code JSX par Babel.
Le code JSX est facile à lire et à écrire. Il s’écrit comme du code HTML, mais il est saisi
dans la partie réservée au code JavaScript (dans la balise <script>). Une même
instruction peut s’écrire sur plusieurs lignes et doit obligatoirement commencer par
une balise ouvrante et se terminer par balise fermante (ici, <ul> et </ul>).
Les instructions JavaScript dans un bloc de code JSX doivent être entourées par des
acco- lades, en particulier l’instruction elems.map(). De même, dans chaque
instruction JSX, toute expression JavaScript doit être encadrée par des accolades, d’où
leur présence dans {styleListe} et {index}.
L’attribut key est similaire à celui utilisé dans le précédent chapitre et permet d’éviter
un aver- tissement lors de l’exécution du code (message d’erreur «Each child in an
array or iterator should have a unique "key" prop.»).
Utiliser la notation ES6 pour définir la fonction
En utilisant la notation => (disponible dans ES6) pour définir la fonction de callback, on
peut écrire plus simplement le code suivant.
Retourner uniquement les éléments <li> dans la fonction (sans l’élément <ul>)
La fonction ne retourne plus l’élément <ul>, donc les accolades qui servaient à indiquer
le code JavaScript à l’intérieur du code JSX ne sont ici plus nécessaires (et si vous les
laissez, elles provoquent une erreur).
En revanche, la méthode ReactDOM.render() doit retourner le code JSX complet,
incluant l’élément <ul>.
Même si l’affichage de la liste est identique au précédent, on voit ici que les éléments
React <ul> et <ListeElements> ont été inversés dans l’arborescence.
Transmettre des attributs dans un élément JSX
On peut transmettre des attributs aux éléments React définis ici en JSX. Par exemple,
le tableau elems pourrait être transmis dans l’attribut elems de l’élément JSX. On peut
créer les attributs que l’on souhaite dans un élément JSX, ces attributs seront transmis
en paramètres de la fonction de traitement dans l’objet props.
Le style est indiqué comme d’habitude sous forme d’objet JSON (ici, { color:"red" }), et
comme c’est une instruction JavaScript, il faut l’entourer des accolades, d’où les
doubles acco- lades que l’on peut voir ici dans l’élément JSX.
Ce style est récupéré dans la fonction au moyen du paramètre props, et il est accédé à
l’aide de props.style dans l’élément JSX définissant chaque élément <li>.
Écriture du programme en déstructurant l’objet props (en ES6)
Le composant <Element> est lui aussi créé avec une fonction dans laquelle les attributs
index, color et elem sont transmis en paramètres dans l’objet props (ici, utilisé sous
forme déstruc- turée). L’attribut key est utilisé pour éviter l’erreur classique de React
indiquant que cet attribut est obligatoire. Toutefois, il ne sert qu’à mettre une clé
différente sur les éléments issus d’une fonction d’itération, donc il est utilisé dans
l’écriture de l’élément <Element> (écrit dans une boucle d’itération), mais pas dans les
paramètres de la fonction Element().
Dans la classe Element, remarquez l’utilisation des doubles accolades pour définir le
style: la première paire d’accolades est utilisée pour indiquer une instruction
JavaScript, la seconde est utilisée pour écrire l’objet sous forme JSON.
On voit sur l’exemple précédent l’utilité de la notation des fonctions en ES6 (avec les
caractères =>) qui évite de perdre la valeur de this dans une fonction de callback.
Toutefois, on peut écrire le programme de façon légèrement différente et ne pas
perdre la valeur de this tout en utilisant le mot-clé function pour la fonction de
callback.
4.5. Utiliser une fonction ou une classe pour créer les composants en JSX ?
Cette question se pose car les deux manières vues précédemment sont similaires et
abou- tissent visiblement aux mêmes résultats.
Comme lorsque l’on s’était posé la question au sujet de la création des fonctions ou
des classes avec les éléments React (par React.createElement() dans le chapitre
précédent), la réponse est similaire:
on utilisera une fonction si l’on n’a pas besoin de créer des propriétés ou des
méthodes pour faciliter les traitements;
on utilisera plutôt une classe si des propriétés ou des méthodes sont nécessaires
pour les traitements.
En fait, une propriété très importante d’un composant sera la propriété state,
permettant de gérer l’état du composant (ceci est étudié dans le chapitre suivant). La
règle observée est que si le composant possède un état, on utilisera une classe pour le
définir (c’est même dans ce cas obligatoire), sinon une fonction sera suffisante.
4.6. Règles d’écriture du code JSX
Un seul élément parent peut être retourné
Plusieurs éléments JSX de même niveau ne peuvent pas être retournés simultanément,
il est obligatoire qu’ils soient encapsulés dans un élément parent, qui sera celui
retourné (pour être unique), les autres éléments étant ses enfants. En général on
utilise un élément <div> englobant l’ensemble, mais React propose aussi d’utiliser un
composant <React.Fragment> jouant ce rôle.
Remarque : Cette règle est valable également si on utilise la méthode
React.createElement(), avec laquelle on doit retourner également un seul élément
React parent.
Utiliser un fragment avec le composant <React.Fragment>
L’ajout d’un parent, tel qu’un élément <div>, fonctionne lorsqu’on souhaite encapsuler
plusieurs éléments retournés dans un seul. L’inconvénient de cette solution est que
cela ajoute un élément <div> supplémentaire dans le code JSX, sans que cela soit
vraiment nécessaire pour l’application React.
Pour cela, React propose un composant spécifique appelé <React.Fragment> que l’on
peut utiliser pour ces cas-là.
function ListeElements(props) {
return <React.Fragment>
<div>Element1</div>
<div>Element2</div>
<div>Element3</div>
</React.Fragment>
}
ReactDOM.render(<ListeElements />,
document.getElementById("app"));
function ListeElements(props) {
return (
<ul>
<li>Element1</li>
<li>Element2</li>
<li>Element3</li>
<li>Element4</li>
<li>Element5</li>
</ul>
)
}
ReactDOM.render(<ListeElements />, document.getElementById("app"));
function ListeElements(props) {
return (
<ul>
<li>Element1</li>
{/* <li>Element2</li>
<li>Element3</li>*/}
<li>Element4</li>
<li>Element5</li>
</ul>
)
}
ReactDOM.render(<ListeElements />, document.getElementById("app"));
function ListeElements(props) {
return (
<ul>
{ props.hideFirstItem ? null : <li>Element1</li> }
<li>Element2</li>
<li>Element3</li>
<li>Element4</li>
<li>Element5</li>
</ul>
)
}
ReactDOM.render(<ListeElements hideFirstItem={true} />,
document.getElementById("app"));