Pour Android Studio, faire l'installation par défaut/Standard (faire Next tout le temps). Une fois l'installation terminée, démarrez Android Studio et et configurex le Virtual device manager:
NPM (Node Package Manager) est le gestionnaire de paquets par défaut pour l'écosystème JavaScript et Node.js, et il est essentiel pour le développement React Native, il permet aussi de gérer les dépendances:
NPM permet d'installer et de gérer toutes les bibliothèques et dépendances nécessaires à votre projet React Native
Ces dépendances sont listées dans le fichier package.json à la racine de votre projet
Voici quelques exemples de commandes:
npm install # Installe toutes les dépendances du projet
npm install nomdupackage # Installe un package spécifique
npm start # Démarre votre application React Native
npm run android # Lance l'application sur Android
npm run ios # Lance l'application sur iOS
Il est à noter que toutes ces dépendances sont stocké dans un fichier: package.json.Ce fichier est crucial car il :
Liste toutes les dépendances de votre projet
Définit les scripts personnalisés pour votre application
Contient les métadonnées de votre projet
Un excellent site, qui est aussi le registre officiel des packages JavaScript/Node.js est : https://www.npmjs.com
NPX est un outil qui permet d'exécuter des packages npm directement sans avoir besoin de les installer globalement sur votre machine. Ceci peut être utilise lorsque nous voulons tester une librairie (permet d'exécuter des outils ponctuellement sans installation permanente) et évite d'encombrer votre système avec des installations global
Lorsque nous avons créé notre première application React Native, le système a créé l'arborescence suivante:
Cette arborescence montre une structure typique d'un projet React Native Expo :
.expo : Configuration Expo (notamment la dernière configuration utilisé lors du démarrage, par exemple démarrage en IOS)
app : Code source de l'application
assets : Ressources (images, polices)
components : Composants réutilisables
constants : Variables constantes
hooks : Hooks personnalisés
node_modules : Dépendances
scripts : Scripts utilitaires
Fichiers importants :
package.json : Dépendances et scripts
app.json : Configuration de l'app
tsconfig.json : Configuration TypeScript
README.md : Documentation
Dans un projet React Native Expo moderne, le point d'entrée principal est souvent App.tsx (si TypeScript) ou est déplacé dans le dossier app/. C'est une structure plus organisée qui sépare mieux les composants. Vous pouvez créer App.js ou App.tsx si vous préférez cette structure. Dans notre projet, le point d'entrée est dans app/(tabs)/index.tsx
Nous allons vérifier les versions dans Visual Code de Node.js
Exécuter dans le terminal de Windows (Shell)
Il faut exécuter cette ligne de commande dans votre terminal de Windows (Shell):
npx create-expo-app@latest
Pour le nom de votre app, voici un nom original :-)
Si tout se passe comme prévu, vous devriez avoir l'écran suivant à la fin de la création de votre application:
Nous allons nous déplacer sur le répertoire de projet:
cd pablothegod
Et démarrer l'installation en mode web:
npm run web
Le fureteur par défaut de votre OS devrait s'ouvrir sur votre dekstop, sinon vous devez pointer celui-ci sur l'adresse que Expo vous présente. Dans mon cas l'adresse est: http://localhost:8081:
Vous pouvez aussi scanner le code QR avec votre mobile et ouvrir l'application sur votre téléphone à travers Expo GO. Voici un rendu sur un iphone:
Prendre note qu'en secouant votre téléphone (shake it!), vous devriez voir les paramètres de configuration de l'app apparaître:
Tu peux, à tout moment, cliquer sur le terminal dans lequel tu as lancé "npx expo start" ou directement sur l'écran de ton émulateur puis appuyer sur la touche "R" pour rafraichir ton application.
Pour commencer notre nouvelle app, nous allons exécuter la commande:
npm run reset-project
En cas d'erreur, (ceci peut arriver si Visual Code est ouvert), fermez celui-ci et recommencer dans le Shell de Windows".
Ceci devrait nous permettre d'avoir un répertoire propre et prêt à être utilisé.
Nous pouvons relancer le projet:
npx expo start
¶ Création de notre première app et de notre premier composant
Nous pouvons maintenant ouvrir Visual Code et éditer le texte du fichier d'entrée app/index.tsx par le code ci-dessous:
import { Text } from "react-native";
export default function App() {
return <Text>HELLO!</Text>;
}
Le résultat sur votre mobile devrait être similaire à ceux-ci:
Sans le réaliser, nous venons d'utiliser notre premier composant React Native. Celui-ci est de type TEXT et nous avons fait appel à celui-ci en imporant la librairie Text (import { Text } from "react-native";) et utilisant les balises <Text> </Text> .
Mais qu'est-ce qui arrive si je veux afficher plusieurs textes?
import { Text } from "react-native";
export default function App() {
return (<Text>HELLO!</Text>
<Text>HELLO!</Text>
<Text>HELLO!</Text>)
}
Ceci amène une erreur:
Ceci nous amène à notre première règle à respecter:
Lorsqu'il y a plusieurs composants, il faut absolument un parent <></> (aussi appelé un fragment)
Le code corrigé devrait être:
import { Text } from "react-native";
export default function App() {
return (
/* Balise parent */
<>
<Text>HELLO!</Text>
<Text>HELLO!</Text>
<Text>HELLO!</Text>
</>
/* Fin de la balise parent */
);
}
Et le résultat sur mobile:
Nous aurions aussi pu mettre le texte dans un composant de type VIEW et avoir le même résultat de sortie.
Afin de s'assurer de ne pas travailler dans la barre de menu du téléphone (Android ou Iphone), nous allons installer la librairie suivante:
npm i react-native-safe-area-context
Nous pourrons alors importer le code suivant:
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
//Importation des composantes
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView>
<Text>Hello</Text>
</SafeAreaView>
</SafeAreaProvider>
);
}
Le résultat sur le mobile devrait ressemble à ceci:
Lors de l'éxécution du code, si vous avez l'erreur suivante, vous pouvez ignorer celle-ci:
Dorénavant, nous allons toujours utilisé les composants SafeAreaProvider et SafeAreView dans notre code.
Si nous reprenons le code de la section précédente et que nous intégrons les 2 composantes, nous avons:
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView>
<View style={s.square}>
<Text style={{ color: 'red', backgroundColor: 'black' }}>
Hello World
</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
Le résultat sur le mobile devrait donner la figure ci-dessous:
Utilisateur de iphone: Avec la nouvelle version de React Native en mode web, le système se position après le notch et explique pourquoi vous n'avez peut-être pas eu de problème d'affichage pour les exercices précédents.
Commencons avec un exemple simple. Nous voulons nous assurer que toute notre ‘view’ est en rouge:
Le code suivant avec l'argument ‘flex: 1’ devrait faire le travail:
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ backgroundColor: 'red', flex: 1 }}></SafeAreaView>
</SafeAreaProvider>
);
}
Le résultat est:
Maintenat, si nous rajoutons une 2e ‘view’ avec la couleur en background en bleu, nous avons:
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ backgroundColor: 'red', flex: 1 }}></SafeAreaView>
<View style={{ backgroundColor: 'blue', flex: 1 }}></View>
</SafeAreaProvider>
);
}
Le résultat est:
On comprends alors que l'argument flex sont pour les proportions.
Pour que la partie en bleue soit 2 fois plus grande que la aprtie en rouge, il faudrait avoir le code suivant:
//Avec 2 views: Surface bleu deux fois plus grande que la surface rouge
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ backgroundColor: 'red', flex: 1 }}></SafeAreaView>
<View style={{ backgroundColor: 'blue', flex: 2 }}></View>
</SafeAreaProvider>
);
}
Le résultat est:
Rajoutons un composant dans notre démo. Nous allons créer un répertoire FlexDemo sous components et rajouter le fichier FlexDemo.jsx et FlexDemo.style.js dans celui-ci.
Le code va être simple, nous allons renvoyer du code vide:
//Code pour FlexDemo.jsx
import { View } from 'react-native';
import { s } from './FlexDemo.style';
//Retourne un vue vide
export function FlexDemo() {
return <View></View>;
}
//Code pour FlexDemo.style.js
import { StyleSheet } from 'react-native';
//Création d'un style vide
export const s = StyleSheet.create({});
Sans oublier de changer le code index.tsx
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
import { FlexDemo } from '../components/FlexDemo/FlexDemo';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ backgroundColor: 'grey', flex: 1 }}>
//J'appelle le composant qui est vide donc aucun résultat visuel attendu
<FlexDemo />
</SafeAreaView>
</SafeAreaProvider>
);
}
Le résultat est le suivant sur un mobile:
Modifions le code pour rajouter 3 classes avec des attributs propres à chacune et 3 objets. Voici le code pour les 2 fichiers:
//Code pour FlexDemo.jsx
//Création de nos 3 objets
import { View } from "react-native";
import { s } from "./FlexDemo.style";
export function FlexDemo() {
return (
<View style={s.container}>
<View style={s.box1} />
<View style={s.box2} />
<View style={s.box3} />
</View>
);
}
Nous n'avons pas besoin de changer le code dans index.tsx puisque celui-ci appelle encore la composante <FlexDemo />
Le résultat final:
Un premier constant que nous pouvons faire et la direction des boîtes. En effet, celle-ci ne se juxtapose pas les une après les autres (en mode horizontale) mais bien sous forme d'une colonne. Par défaut, la direction des flexbox est en colonne et la propriété par défaut est: flexdirection: ‘column’
Si nous voulons que les flexbox soient une à côté des autres, il faut utilisé la propriété: flexdirection: ‘row’
Attention, le texte est sensible à la case (case sensitif). flexdirection: ‘row’ ne donne pas le même résultat que flexDirection: ‘row’
Dans le cas où nous voulons justifier et centrer les flex box, nous pouvons utiliser le paramètre: justifyContent: “center”. Prendre note que ce paramètre travaille dans le même sens que flexdirection
import { StyleSheet } from 'react-native';
export const s = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'green',
//Par défaut, s'il n'y pas de paramètre alors nous sommes en direction 'colonne'
//La justification se fait dans le même sens que la direction de la flex box, c'est-à-dire en colonne
justifyContent: 'center',
},
box1: {
height: 100,
width: 100,
backgroundColor: 'blue',
},
box2: {
height: 100,
width: 100,
backgroundColor: 'white',
},
box3: {
height: 100,
width: 100,
backgroundColor: 'red',
},
});
Le résultat est:
Le paramètre alignItemstravaille dans le sens opposé à la direction de la flex box.
flex: 1,
backgroundColor: 'green',
//Par défaut, s'il n'y pas de paramètre alors nous sommes en direction 'colonne'
//La justification se fait dans le même sens que la direction de la flex box, c'est-à-dire en colonne
justifyContent: 'center',
//L'alignement se fait dans la direction opposée à la flex box
alignItems: 'center',
En résumé, les trois propriétés suivantes travaillent conjointement:
Attention: Les exemples de la vidéo sont pourReact. Nous travaillons avecReact native et il faudra modifier les exemples, notamment les propriétés des boutons:
Il faut se créer son composant et son style correspondant:
Voici le code correspondant pour Article.jsx:
//Article.jsx
import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { s } from './Article.style';
export const Article = () => {
return (
<View style={s.container}>
<Text style={s.title}>Hello World</Text>
<Text style={s.paragraph}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus et
diam et lorem scelerisque ullamcorper. Donec vel dui vel tortor
tincidunt finibus. Donec aliquam ligula dolor, molestie sollicitudin
quam lobortis vitae. Nullam ac ante eget est commodo luctus eu vitae
turpis. Donec non dui vel nisl faucibus consectetur et non velit.
Phasellus quis tristique nunc. Suspendisse suscipit malesuada velit
congue hendrerit. Orci varius natoque penatibus et magnis dis parturient
montes, nascetur ridiculus mus.
</Text>
</View>
);
};
Voici le code correspondant pour Article.style.js:
Une prop (abréviation de "property") dans React Native est un mécanisme pour passer des données d'un composant parent à un composant enfant.
Voici un exemple:
// Composant parent (App.tsx)
export default function App() {
return (
<Human name="John" age={25} />
);
}
// Composant enfant (Human.tsx)
type HumanProps = {
name: string;
age: number;
}
export function Human(props: HumanProps) {
return (
<Text>
Je m'appelle {props.name} et j'ai {props.age} ans
</Text>
);
}
Les props peuvent être :
Des chaînes de caractères
Des nombres
Des booléens
Des objets
Des fonctions
Des composants
Les props sont immutables (ne peuvent pas être modifiées) dans le composant enfant. Si vous avez besoin de modifier des données, il faut utiliser le state (useState).
Revenons dans notre code initiale (index.tsx) et changeons notre flex box <FlexDemo /> par notre composant <Human /> :
//Fichier index.tsx
//Exemple avec le composant Human
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
import { FlexDemo } from '../components/FlexDemo/FlexDemo';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }}>
<Human />
</SafeAreaView>
</SafeAreaProvider>
);
}
Nous avons le résutlat:
Nous allons utiliser les props pour envoyer les infos au composant enfant:
//Fichier index.tsx
//Exemple avec Human
import { Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
import { FlexDemo } from '../components/FlexDemo/FlexDemo';
//Avec les props, je peux envoyer ce que je veux (booléen, fonction, ...)
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }}>
<Human
firstName={'Pablo'}
lastName={'Pardo'}
age={25}
car={{ brand: 'Rolls-Royce', maxSpeed: 360 }}
isRich={true}
doSomething={function () {
console.log('Pablo is the God!');
}}
/>
</SafeAreaView>
</SafeAreaProvider>
);
}
Dans fichier Human.jsx, la fonction Human peut accéder aux props de la façon suivante:
Je peux donc écrire le code suivant:
//Human.jsx
import { Text } from 'react-native';
export function Human(props) {
return (
<Text style={{ fontsize: 40 }}>
Mon prénom est {props.firstName} et mon nom est {props.lastName}
</Text>
);
}
Le résultat sur le téléphone donne:
Je peux aussi déconstruire mon props (afin d'éviter d'avoir à écrire ‘props.’ pour chaque attribut:
//Human.jsx
//On peut déconstruire le props aussi et ainsi aller chercher les attributs directement. Cela évite de répeter le 'props.'pour chaque attriuts.
import { Text } from 'react-native';
export function Human({ firstName, lastName }) {
return (
<Text style={{ fontsize: 40 }}>
Mon prénom est {firstName} et mon nom est {lastName}
</Text>
);
}
Attention à l'objet car. En effet, en cas de déconstruction, il va falloir appeler chacun de ces attributs (ex: car.brand):
//Human.jsx
//Objet Car
import { Text } from 'react-native';
export function Human({ firstName, lastName, car }) {
return (
<>
<Text style={{ fontsize: 40 }}>
Mon prénom est {firstName} et mon nom est {lastName}
</Text>
<Text style={{ fontsize: 40 }}>Ma voiture est une {car.brand}</Text>
</>
);
}
Le résultat est:
Fun fact: Le modèle Phantom IV de Rolls-Royce était exclusif aux membres de la royauté.
Phantom IV
Dans le cas où nous voulons rajouter l'image ci-haut dans notre composant, nous pouvons consulter la documentation officielle de React Native:
Nous pouvons modifier le code afin que l'enfant envoie une props à son parent. Par exemple, l'enfant va envoyer une image à son parent. En reprennant notre exemple:
//Fichier index.tsx
//Ne pas oublier d'importer la librairie Image
import { Image, Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
import { FlexDemo } from '../components/FlexDemo/FlexDemo';
//On va envoyer une image comme props en dehors de l'objet Human
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }}>
<Human
firstName={'Pablo'}
lastName={'Pardo'}
age={25}
car={{ brand: 'Rolls-Royce', maxSpeed: 360 }}
isRich={true}
doSomething={function () {
console.log('Pablo is the God!');
}}
>
<Image
style={{ height: 200, width: 300 }}
source={{
uri: 'https://media.goodingco.com/image/upload/c_fill,g_auto,q_88,w_1799/v1/Prod/Archives/PB11%20—%20Pebble%20Beach%20Auctions%202011/132._1952_Rolls-Royce_PhIV_DSCF0976_aust9o',
}}
/>
</Human>
</SafeAreaView>
</SafeAreaProvider>
);
}
Ne pas oublier d'importer la librairie Image:
import { Image, Text, View } from 'react-native';
Et nous allons modifier le fichier de componsate:
import React from 'react';
import { Image, Text, StyleSheet } from 'react-native';
import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context';
//Props enfant à parent: children
export function Human({ firstName, lastName, car, children }) {
return (
<>
<Text style={{ fontsize: 40 }}>
Mon prénom est {firstName} et mon nom est {lastName}
</Text>
<Text style={{ fontsize: 40 }}>Ma voiture est une {car.brand}</Text>
{children}
</>
);
}
Nous devrions avoir un réulstat similaire au code précédent, soit:
Ce qui est intéressant c'est que ce children est générique, c'est-à-dire qu'il peut être n'importe quoi et nous pouvons le changer. Nous avions une image mais nous pouvons envoyer du texte à la place sans avoir à modifier le children. Par exemple, l'image de la voiture va être remplacer par du texte:
//Ne pas oublier d'importer la librairie Image
import { Image, Text, View } from 'react-native';
import { Human } from '../components/Human/Human';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { s } from '../App.style';
import { FlexDemo } from '../components/FlexDemo/FlexDemo';
//On va envoyer une image comme props en dehors de l'objet Human
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }}>
<Human
firstName={'Pablo'}
lastName={'Pardo'}
age={25}
car={{ brand: 'Rolls-Royce', maxSpeed: 360 }}
isRich={true}
doSomething={function () {
console.log('Pablo is the God!');
}}
>
<Text style={{ fontSize: 50 }}> Wesh!!!</Text>
</Human>
</SafeAreaView>
</SafeAreaProvider>
);
}
Prenons la variable booléenne que nous avons créée précédement (isRich). Par défaut, une variable booléenne non initialisé est TRUE. Je vous remémore la mémoire:
Les booléens ont deux valeurs possibles en programmation :
true (vrai)
false (faux)
En JavaScript/React Native, il y a aussi des valeurs qui sont considérées comme "falsy" (évaluées comme false) :
Un state est un objet qui contient des données qui peuvent changer au fil du temps et qui, lorsqu'elles changent, déclenchent un re-rendu (rendering) du composant. Afin de mieux visualiser la différence entre state et un props, voici un diagramme qui vous permettra de mieux comprnedre la différence entre les deux:
Pour comprendre les state, nous allons nous faire un exemple de compteur en créant un componsant AgeCounter:
Voici le code du composant AgeCounter:
//Fichier composant AgeCounter.tsx
import { Text, TouchableOpacity } from 'react-native';
export function AgeCounter() {
let age = 30;
function increaseAge() {
console.log(age);
age = age + 1;
console.log(age);
}
return (
<>
<TouchableOpacity onPress={increaseAge}>
<Text>Augementer</Text>
</TouchableOpacity>
<Text>J'ai {age} ans</Text>
</>
);
}
Dans React, les boutons sont appelés des Touchable. Le bouton avec l'effet relief est un TouchableOpacity
Remarquez le codeonPress={increaseAge}. L'appel de la fonction se fait sans les double parenthèse (): onPress={increaseAge()}
Voici le code dans le fichier index.tsx
//Fichier index.tsx
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
//Ne pas oublier d<importer le composant
import { AgeCounter } from '../components/AgeCounter/AgeCounter';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }}>
<AgeCounter />
</SafeAreaView>
</SafeAreaProvider>
);
}
Voici le résultat en sorite (après avoir appuyé sur le bouton Augmenter)
Question: Pourquoi l'âge ne se mets pas à jour?
Les variables telles que définies dans notre fonction, ne sont pas ‘réactives’, c'est-à-dire qu'elles ne vont pas entraîner de rafraichissement (rendering) du côté client. C'est la raison pourquoi il faut utiliser les states!
Recommencons avec un nouveau composant mais cette fois, en utilisant la notion de state et surtout, la fonction useState.
useState est aussi connu sous le nom de hooks dans React Native. Les Hooks sont des fonctions spéciales qui permettent de "se connecter" (to hook into) aux fonctionnalités de React, comme la gestion d'état et le cycle de vie des composants, dans les composants fonctionnels.
Le code du fichier AgeCounter.jsx devient:
//Fichier AgeCounter.jsx
//Ne pas oublier d'importer la librairie useSate
import { useState } from 'react';
import { Text, TouchableOpacity } from 'react-native';
//Variable avec state
export function AgeCounter() {
const [age, setAge] = useState(30);
function increaseAge() {
setAge(age + 1);
}
return (
<>
<TouchableOpacity onPress={increaseAge}>
<Text>Augementer</Text>
</TouchableOpacity>
<Text>J'ai {age} ans</Text>
</>
);
}
Il est maintenant possible d'augmenter son âge en appuyant sur le bouton Augmenter.
Nous aurions pu aussi envoyer un objet. Voici le code:
//Ne pas oublier d'importer la librairie useSate
import { useState } from 'react';
import { Text, TouchableOpacity } from 'react-native';
//Variable avec un objet
export function AgeCounter() {
const [age, setAge] = useState(30);
const [data, setData] = useState({ color: 'Red', speed: 200 });
function increaseAge() {
setAge(age + 1);
setData({ color: 'Blue', speed: data.speed + 1 });
}
return (
<>
<TouchableOpacity onPress={increaseAge}>
<Text>Augementer</Text>
</TouchableOpacity>
<Text>
J'ai {age} ans et je suis de couleur {data.color} et ma vitesse est{' '}
{data.speed}
</Text>
</>
);
}
Le callback est une fonction qui est envoyée à un enfant à travers un props. Le composant enfant a alors la possibilité d'executer (déclencher) la fonction. Le callback et donc un moyen de communiquer des composants enfants vers les parents.
L'image montre le flux d'une fonction callback à travers les composants:
Une fonction (hello) est passée comme prop d'un composant parent à un composant enfant
Le composant enfant peut ensuite passer cette prop à un autre composant
La fonction hello() est finalement exécutée
Le résultat ("Coucou !") est affiché via alert()
Le callbackest mécanisme fondamental dans React Native pour :
Passer des fonctions entre composants
Gérer la remontée d'informations des composants enfants vers les parents
Pour détecter la plateforme sous React Native, vous pouvez utiliser Platform de 'react-native'.
import { Platform } from 'react-native';
// Méthode 1 : Platform.OS
const plateforme = Platform.OS; // Retourne 'ios' ou 'android'
// Méthode 2 : Platform.select
const styles = {
container: Platform.select({
ios: {
backgroundColor: 'red'
},
android: {
backgroundColor: 'blue'
}
})
}
// Méthode 3 : Vérification conditionnelle
if (Platform.OS === 'ios') {
// Code spécifique à iOS
} else {
// Code spécifique à Android
}
// Méthode 4 : Pour vérifier la version d'Android
if (Platform.Version > 25) { // Android 7.1+
// Code pour les versions récentes d'Android
}
// Méthode 5 : Pour vérifier la version d'iOS
if (parseInt(Platform.Version, 10) >= 13) {
// Code pour iOS 13+
}
Platform dans React Native permet de détecter les plateformes suivantes :
'ios' - Pour les appareils iOS (iPhone, iPad)
'android' - Pour les appareils Android
'web' - Pour les applications React Native Web
'windows' - Pour les applications Windows (via React Native Windows)
'macos' - Pour les applications macOS (via React Native macOS)
Voici un petit exemple en réutilisant notre code (index.tsx)
//Détecter plateforme
import { useState } from 'react';
import { Platform, Alert, Text, TouchableOpacity } from 'react-native';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { Child } from '../components/Child/Child';
export default function App() {
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }}>
{Platform.OS === 'ios' ? (
<Text>Hello sur IOS</Text>
) : (
<Text>Hello sur Android</Text>
)}
</SafeAreaView>
</SafeAreaProvider>
);
}
Voici le résutlat sur les mobiles:
Voici un code qui permet de change le fond de couleur selon la palteforme:
import { Platform } from 'react-native';
// Vérifie la plateforme actuelle
console.log(Platform.OS); // Affichera 'ios', 'android', 'web', 'windows' ou 'macos'
// Exemple d'utilisation avec Platform.select
const styles = Platform.select({
ios: {
backgroundColor: 'red'
},
android: {
backgroundColor: 'blue'
},
web: {
backgroundColor: 'green'
},
windows: {
backgroundColor: 'yellow'
},
macos: {
backgroundColor: 'purple'
},
default: {
backgroundColor: 'gray' // Fallback pour toute autre plateforme
}
});
À noter que pour que la détection fonctionne sur web, windows et MacOs, vous devez avoir installé et configuré les packages correspondants (react-native-web, react-native-windows, react-native-macos).
Faire une application avec un bouton simple et un background rouge. Lorsque l'utilisateur appuie sur le bouton, la couleur devient un peu plus foncé à chaque fois.