Aller au contenu principal

Composants et JSX

Une interface, c'est une fonction qui reçoit des données et renvoie ce qu'il faut afficher.

Objectifs de la séance​

  • comprendre ce qu'est un composant et ce qu'est le JSX ;
  • insérer des valeurs dans le JSX avec les accolades { } ;
  • transmettre des données à un composant avec les props ;
  • afficher une liste avec map et la propriété key ;
  • afficher un élément seulement si une condition est vraie, sans piège.

Notions théoriques​

Un composant, c'est une fonction​

Dans une application Expo, chaque morceau d'écran est un composant : une simple fonction qui renvoie ce qu'il faut afficher. Cette description s'écrit en JSX, une syntaxe qui ressemble beaucoup au HTML.

import { Text, View } from "react-native";

export default function App() {
return (
<View>
<Text>Bonjour le quiz !</Text>
</View>
);
}

Vous reconnaissez tout ce que vous avez appris : une fonction, return, export default (obligatoire pour un écran), des parenthèses autour du retour sur plusieurs lignes.

Les briques de React Native​

En HTML, vous utilisiez <div>, <p>, <button>. En React Native (Expo), les briques ont d'autres noms :

HTMLReact NativeRôle
<div><View>conteneur
<p>, <span>, <h1><Text>tout texte
<button><Pressable>zone sur laquelle on appuie
<img><Image>image
Tout texte doit être dans un composant Text

Contrairement au HTML, un texte écrit directement dans un <View> provoque une erreur (« Text strings must be rendered within a <Text> component »). Tout texte, même un nombre, doit être placé dans un <Text>.

Insérer des valeurs avec { }​

Dans le JSX, les accolades permettent d'insérer n'importe quelle expression JavaScript (variable, calcul, appel de fonction).

const joueur = "Alice";
const score = 7;

<Text>Bravo {joueur} ! Votre score : {score * 10} points</Text>

Les accolades ne servent pas à écrire des instructions (if, for) : seulement des expressions (valeurs).

Les règles du JSX​

  1. un composant renvoie un seul élément racine (enveloppez plusieurs éléments dans un <View> ou un fragment <>...</>) ;
  2. toute balise doit être fermée : <Text>...</Text> ou <Image /> ;
  3. le nom d'un composant commence par une majuscule (CarteQuestion), pour le distinguer des balises natives ;
  4. les attributs sont écrits en camelCase, et un objet de style prend deux paires d'accolades : style={{ padding: 8 }}.

Les styles​

Les styles ne s'écrivent pas en CSS mais en objets JavaScript, regroupés avec StyleSheet.create.

import { StyleSheet, Text, View } from "react-native";

<View style={styles.carte}>
<Text style={styles.titre}>Quiz Cyber</Text>
</View>

const styles = StyleSheet.create({
carte: { backgroundColor: "white", padding: 16, borderRadius: 8 },
titre: { fontSize: 24, fontWeight: "bold" },
});

Les noms sont en camelCase (backgroundColor, pas background-color) et les valeurs numériques n'ont pas d'unité.

Les props : donner des données à un composant​

Un composant devient réutilisable quand on lui transmet des données, qu'il reçoit dans un objet appelé props. Vous reconnaissez la destructuration de paramètres de la partie 3.

type CarteQuestionProps = {
enonce: string;
niveau: number;
};

function CarteQuestion({ enonce, niveau }: CarteQuestionProps) {
return (
<View>
<Text>{enonce}</Text>
<Text>Niveau {niveau}</Text>
</View>
);
}

// Utilisation : les props s'écrivent comme des attributs
<CarteQuestion enonce="À quoi sert un VPN ?" niveau={2} />

Les props sont en lecture seule : un composant ne modifie jamais ses props (comme une fonction pure ne modifie pas ses arguments). Pour un texte, on écrit enonce="..." ; pour tout le reste (nombre, variable, booléen), on utilise les accolades : niveau={2}.

Afficher une liste : map et key​

Pour afficher un tableau, on utilise map (partie 3) qui transforme chaque donnée en composant.

{questions.map((question) => (
<CarteQuestion
key={question.id}
enonce={question.enonce}
niveau={question.niveau}
/>
))}

La propriété key est obligatoire : elle permet à React d'identifier chaque élément quand la liste change. Elle doit être unique et stable, comme l'id de la donnée.

Pas l'indice comme key

N'utilisez pas l'indice du tableau (key={index}) quand la liste peut être modifiée, triée ou filtrée : React s'y perdrait et pourrait afficher des données mélangées. Utilisez l'id.

Afficher selon une condition​

Deux écritures pour afficher un élément seulement si une condition est vraie :

{indice ? <Text>Indice : {indice}</Text> : null} // ternaire : sûre, claire
{estTerminee && <Text>Partie terminée</Text>} // && : pratique, mais avec un piège
Le piège de && avec un nombre

{nombre && <Text>...</Text>} : si nombre vaut 0, JavaScript renvoie 0... et React Native tente d'afficher un 0 en dehors d'un <Text>, ce qui fait planter l'écran. Utilisez un ternaire (nombre > 0 ? <Text>...</Text> : null) ou une condition booléenne claire (nombre > 0 && ...).


Test de mémorisation/compréhension​


Qu'est-ce qu'un composant React Native ?


Quelle balise doit contenir tout texte affiché en React Native ?


Comment affiche-t-on la variable joueur dans un composant Text ?


Que sont les props d'un composant ?


Quelle valeur faut-il donner à key dans une liste de questions ?


Pourquoi {nombre && <Text>Bravo</Text>} est-il risqué quand nombre vaut 0 ?



TP pour réfléchir et résoudre des problèmes​

Votre mission : afficher la liste des questions du quiz sous forme de cartes. Dans Expo Snack, remplacez le contenu de App.tsx au fil des étapes.

Point de départ :

import { StyleSheet, Text, View } from "react-native";

type Question = {
id: number;
enonce: string;
niveau: 1 | 2 | 3;
indice?: string;
};

const questions: Question[] = [
{ id: 1, enonce: "Quel mot de passe est le plus robuste ?", niveau: 1, indice: "Pensez à la longueur" },
{ id: 2, enonce: "Qu'est-ce que l'hameçonnage ?", niveau: 1 },
{ id: 3, enonce: "À quoi sert un VPN ?", niveau: 2 },
];

Étape 1 — Définir les props d'une carte​

Décrivez les props de CarteQuestion : l'énoncé, le niveau, et un indice facultatif.


Bonne pratique - Un type par composant

Décrire les props avec un type nommé (CarteQuestionProps) documente le composant : en lisant ce type, on sait ce qu'il faut lui donner.

Étape 2 — Écrire le composant​

Écrivez l'ouverture du composant avec la destructuration des props.


Bonne pratique - Majuscule au nom du composant

CarteQuestion commence par une majuscule : React reconnaît ainsi un composant et ne le confond pas avec une balise native.

Étape 3 — Afficher la liste​

Dans App, affichez une carte par question.


Bonne pratique - key sur l'élément du map

La key se place sur l'élément le plus extérieur renvoyé par le map (ici CarteQuestion), pas dans un composant enfant.

Étape 4 — Afficher l'indice seulement s'il existe​

Dans CarteQuestion, ajoutez une ligne d'indice uniquement quand indice est renseigné.


Bonne pratique - Ternaire plutôt que && pour les valeurs incertaines

null ne s'affiche pas. Avec un ternaire, vous ne risquez jamais d'afficher par erreur un 0 ou un texte vide hors d'un <Text>.

📌 Une solution

Ce qu'il faut retenir​

NotionRésumé
ComposantFonction (nom en majuscule) qui renvoie du JSX ; un écran est un export default.
JSXSyntaxe proche du HTML ; { } insère une expression JavaScript ; tout texte dans un <Text>.
BriquesView (conteneur), Text (texte), Pressable (appui), Image.
PropsDonnées reçues du parent, en lecture seule, décrites par un type et destructurées.
Listesliste.map((x) => <Composant key={x.id} ... />) avec une key unique et stable.
Conditioncondition ? <A /> : null ; attention à && avec un nombre (le 0 plante).

Aperçu de la prochaine séance​

Votre écran est joli, mais figé. Dans la prochaine séance, vous allez le rendre vivant : un bouton, un score qui augmente, un écran qui se met à jour tout seul grâce à useState. Vous y retrouverez la destructuration de tableau, les fermetures et la règle « ne jamais modifier, toujours copier ».