REACT NATIVE – P3 - page 1/104
REACT NATIVE
-
SOMMAIRE
Sommaire ... 1
Etape 1 ... 6
1 - React Native : développement multi-plateformes en JavaScript ... 6
Qu’est-ce que c’est ?... 6
Objectifs ... 6
Pérénité et concurrence ... 6
Sites internet ... 6
2 - Installations ... 7
Objetifs de l’installation... 7
Mise en garde : attention ... 8
Les outils de base ... 9
Node.js ... 9
git ...10
watchman (pour MAC)...11
VSCode ...11
Yarn ...11
PowerShell (Windows) ...11
Compléments d’installation ... 12
Désinstallation Mac : ...12
Application expo : https://expo.io/ ... 13
1 - Principes d’expo ...13
2 - Créer un compte ...13
3 - Documentation expo : https://docs.expo.io/ ...14
4 - Les outils : https://expo.io/tools ...14
5 - Guide d’installation : https://docs.expo.io/get-started/installation/ ...14
6 - Installation d’Expo CLI : https://docs.expo.io/get-started/installation/#1-expo-cli ...15
7 - Installation d’Expo Go : https://docs.expo.io/get-started/installation/#2-expo-go-app-for-ios-and ...16
3 - Créer une première application – v3.2...17
Situation ... 17
Première application : https://docs.expo.io/get-started/create-a-new-app/ ... 18
Création d’une application ...18
Contenu de l’application ...18
Démarrage du serveur de développement : ...19
Voir l’application sur son téléphone : scanner le QR code ...20
Voir l’application sur Android Studio ...20
Voir l’application sur son navigateur web : ...20
Organisation du code v3.2 ... 21
VS code...21
Contenu de l’application ...22
node_modules : npm update ...22
App.js ... 23
Le fichier App.js ...23
Premières modifications du contenu (HTML-XML) ...24
Premières modifications du style (CSS) : ...25
Outils supplémentaires : snack et doc... 26
Utilisation de Snack...26
Références React-native : ...27
Synthèse des commandes, du code et de l’architecture ... 28
Commandes ...28
Code ...28
Contenu de l’application ...29
4 - Créer une première architecture ...30
Installation ... 30
Par copie de « my-app-expo » ...30
Par création de « my-app-expo 2 » ...30
Mise en place d’une première architecture ... 31
Principe ...31
Créations de nouveaux dossiers ...31
Créations d’un nouveau contenair : Vue ...31
Mise en place des composants ... 32
Vue.js...32
index.js ...32
Adaptation du fichier App.js ...33
Test du code ...33
Mise en place du style ... 34
Vue.style.js – version 1 ...34
Vue.js...34
Test du code ...34
Vue.style.js – version 2 ...35
Prise en compte des styles dans la Vue ...35
Test du code ...35
Bilan UML du code ... 36
Synthèse des commandes, du code et de l’architecture ... 37
Commandes ...37
Code ...37
5 - API Reference expo : https://docs.expo.io/versions/latest/ ...38
API React Native...38
Expo SDK ...38
Etape 2 ...39
6 – Application « twitterapp » ...39
1-Structure : main et App ... 39
2-Création d’un tableau de tweets v4.1 ... 39
3-Affichage d’un tweet ... 40
Main.js v4.2 ...40
4-Gestion de l’image v4.3 ... 41
Gestion de l’image ...41
A ce stade, on à cette situation : ...42
5-Création d’un composant avec des paramètres v4.4 ... 43
Principes ...43
Tweet.js ...44
Tweet.styles.js...44
Main.js...45
6-Bilan UML du code ... 46
REACT NATIVE – P3 - page 3/104
9-Afficher tous les tweets ... 53
Version sans boucle ...53
On peut avoir une erreur : ...53
Parenthèse : livraisons légères ...55
Objectif ... 55
Dossiers et fichiers à supprimer ... 55
Réinstallation ... 55
7 – Boucle pour afficher tous les tweets v4.6 ...56
Rappels de syntaxe sur les boucles ... 56
Boucle « for » : rappel ...56
boucle « for key in » : rappel ...56
méthode forEach() : rappel ...56
méthode map() : rappel ...57
méthode filter() : rappel ...57
Bien distinguer un map d’un forEach ...57
Afficher tous les tweets : version compacte ... 58
Solution – 1 – compact mais avec warning ...58
On a un warning : ...58
Principe du spread operator ici : … ...58
Rappels sur Spread operator : …...59
Solution – 2 – compacte, sans warning (la bonne !)...60
Solution – 3 – on ajoute des filtres ...61
Solution – 4 – exemple d’ajout d’affichage en plus des tweets ...62
Solution – 5 – version sans spread ...63
Solution – 6 – version avec class et spread et filtre...64
8 – Composant statefull : interaction utilisateur – 1/2 ...65
Objectif ... 65
Composant « statefull » v5.1 ... 65
Premier codage de TweetBox, sans state ... 66
index.js ...66
TweetBox.js ...66
TweetBox.style.js ...66
Main.js...66
Une balise Input dans le TweetBox v5.2 ... 67
Principes ...67
La balise TextInput ...67
Les attributs de la balise TextInput ...68
TweetBox.style.js ...68
Et les states ? ... 69
L’état du composant ...69
Déclaration d’un state ...69
Ajout d’un événement : onChangeText ...69
La function-méthode « setValue »...69
Comment vérifier qu’on a bien fait le travail ? v5.3 ...70
Bilan ...70
Simplification ...71
Explication ...71
Dernier point : initialiser le <TextInput>...71
Code final ...72
Explication ...72
Style...73
9 – Composant statefull : interaction utilisateur – 2/2 ...74
Objectif v5.4 ... 74
Création d'un bouton pour enregistre le tweet ... 74
Principes ...74
Code : sous le <TextInput> de la TweetBox ...74
Que faire dans setDansTweets ? ... 75
Principes ...75
Solution technique ...75
Conséquences ...76
Différences avec React : pas de constructor() ...76
Reste à écrire setDansTweets ...76
Il faut passer setDansTweets en paramètre de TweetBox pour le récupérer dans le Button ...77
Bilan ...77
Il nous reste à enregistrer le tweet dans setDansTweets du Main ...78
Conclusion ... 79
10 – Finalisation v5.5 ...80
La date ... 80
id unique ... 81
Problème ...81
Un package...81
Une function ...81
Un peu de style ... 82
StatusBar ... 82
Effacer le tweet saisi ... 83
On évite les tweets vides ... 83
L’API Keyboard pour masquer le clavier... 83
ScrollView ... 84
React does not recognize the enterKeyHint prop on a DOM element ... 84
Etape 3 ...85
11 – Application sur plusieurs écrans ...85
Objectif : menu de navigation ... 85
Fonctionnalités ...85
Technique...85
L'écran de test : ... 86
Modification du composant App ... 87
Situation précédente : mono-page ...87
Principes d’une solution multi-pages ...87
Première solution ...87
Deuixème solution ...88
onPress, Button et Handling-touches ... 89
Des icônes dans notre menu ... 90
Solution expo : ...90
Solution React Native Elements : ...91
React Native Elements : v6.3 ... 92
Présentation ...92
Installation : ...92
Composant Text ...92
Button ...93
Etape 4 ...94
12 – Application sur plusieurs écrans ...94
API AsyncStorage ... 94
Objectifs ...94
REACT NATIVE – P3 - page 5/104
Utilisation des méthodes de stockage... 100
Principe general : dans le Main...100
Principe pour afficher les tweets ...100
Solution : le cycle de vie react ...101
Principe pour ajouter un tweet ...103
ETAPE 1
1 - React Native : développement multi-plateformes en JavaScript
Qu’est-ce que c’est ?
React Native est un framework développé par les équipes de Facebook à partir de 2015.
React Native suit le développement de React (2011: fil d'actualité Facebook, 2012 : instagram, 2013 : React opensource)
Plus :
− <ici> : on peut regarder la vidéo
− et <là>
Objectifs
Accélérer le développement et la maintenance des applications mobiles.
Développement multi-plateforme : 1 seul code pour iOS et Androïd.
• https://www.inovex.de/blog/react-native-vs-native-development/
Pérénité et concurrence
Il existe de nombreux frameworks permettant de développer des applications multiplateformes.
Ancêtre : Cordova
Parmi les plus populaires en 2020 :
Ionic : technologie Google (Google c’est aussi Angular)
React Native : technologie Facebook Il faut choisir !
Sites internet
• https://reactnative.dev/
• https://reactnative.dev/docs/getting-started
• https://docs.expo.io/ : expo propose des outils pour tester son code sur son téléphone.
REACT NATIVE – P3 - page 7/104
2 - Installations
Objetifs de l’installation
• Création d’une application et exécution sur navigateur et sur téléphone.
# create d’une application appelée appTest expo init appTest
cd appTest
expo start --web
# scanner le QRcode sur son téléphone expo start
• Cette première application affichera dans un navigateur et sur notre téléphone :
• C’est minimaliste ! Mais toute l’architecture sera là.
Mise en garde : attention
L’installation peut s’avérer compliquée (ou se passer sans problème) ! Il ne faut pas se décourager
!
Ces installations nécessitent souvent le passage de commandes en ligne dans un terminal.
Il faut regarder les messages fournis par les commandes en ligne, particulièrement les messages du
« npm » qui donnent des solutions aux éventuels problèmes.
Il faut chercher sur Google des solutions.
Accrochez-vous. On finit par y arriver !
REACT NATIVE – P3 - page 9/104
Les outils de base
https://docs.expo.io/get-started/installation/
Node.js
• https://nodejs.org
which node node -v npm -v
Mettre à jour node (sur MAC)
>sudo npm cache clean -f
>sudo npm install -g n
>sudo n stable
Mettre à jour nmp (sur MAC)
>sudo npm install npm@latest -g
• Il faut parfois faire un
>npm audit fix
Version adaptée à expo (react-native) en mars 2021 :
>npm --version 6.14.11
> node --version v14.16.0
git
https://git-scm.com/downloads
− MAC :
# dernière version de git brew upgrade git
git --version which git
brew unlink git && brew link git
# installer git-gui brew install git-gui git-gui --version which git-gui which gitk
brew unlink git-gui && brew link git-gui
# brew link --overwrite git-gui
# démarrer gitk gitk
GUI client : https://git-scm.com/downloads/guis
− GitHub desktop : https://desktop.github.com/
REACT NATIVE – P3 - page 11/104 watchman (pour MAC)
https://facebook.github.io/watchman/docs/install#buildinstall
brew update
brew install watchman
VSCode
https://code.visualstudio.com/download Yarn
https://classic.yarnpkg.com/en/docs/install
npm install --global yarn yarn --version
PowerShell (Windows)
https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on- windows?view=powershell-7.1
Compléments d’installation Désinstallation Mac :
echo $PATH
which node : pour savoir lequel fonctionne
suppression d’un dossier sur mac : rm -rf nomDossier sudo rm -R : c’est définitif !
sudo npm uninstall --global npm
REACT NATIVE – P3 - page 13/104
Application expo : https://expo.io/
1 - Principes d’expo
Expo interprète du JavaScript dans son application Expo CLI et saura créer des application natives (iOS ou Android) à déployer sur Google Play ou sur l’App Store.
Expo permet de tester son code sur son téléphone grâce à une application cliente : Expo Go, pour iOS ou Androïd.
2 - Créer un compte
Ca va nous servir. On peut se connecter à partir de son compte GitHub.
Une fois connecté, on arrive sur une page comme ça :
• Menu « votre icône » haut-droite / Projects – Snacks – Settings – Log out
3 - Documentation expo : https://docs.expo.io/
Sur la page d’accueil d’expo.io, on peut faire des recherches et il y a un glossaire. Par exemple, le XDE est devenu expo-cli.
4 - Les outils : https://expo.io/tools
Pour développer en multi-plateforme et avoir un simulateur multi-plateforme (Android et IOS).
• On aura :
− une application sur sa machine développer une application : « l’expo-cli » ou Expo CLI : Command Line Client.
− une application sur son téléphone pour le test : Expo Go, client iOS ou client Androïd.
On peut alors se passer de XCode (développement iOS) et d’Android.studio (développement Android).
5 - Guide d’installation : https://docs.expo.io/get-started/installation/
Ouvrez la documentation dans Chrome et traduisez automatiquement !
REACT NATIVE – P3 - page 15/104
6 - Installation d’Expo CLI : https://docs.expo.io/get-started/installation/#1-expo-cli On télécharge expo-cli : npm install expo-cli --global
Le --global permet d’avoir une application
− MAC :
# suppression de expo-cli -> infos sudo npm -g uninstall expo-cli –save
# yarn pour supprimer toutes les dépendances yarn global remove expo-cli
sudo npm install expo-cli -–global expo-cli --version
# 4.1.6
− On peut faire 2 fois l’install. Il reste des warnings, mais c’est bon ! How to fix the npm can't find package.json error ?
− initialiser le package.json :
npm init -y
− mise à jour du package.json pour git : (changer le username)
"repository": { "type": "git",
"url": "git://github.com/username/repository.git"
},
− mise à jour du package.json pour git : (donner une description)
"description": "test",
Mise à jour de expo-cli
npm install -g expo-cli
7 - Installation d’Expo Go : https://docs.expo.io/get-started/installation/#2-expo-go-app-for-ios-and Deux options pour tester son code :
− Installer une application cliente sur son téléphone : iOS ou Android -> solution légère
− Installer un émulateur iOS ou Android sur son ordinateur -> solution lourde Solution légère : Expo GO
− https://docs.expo.io/get-started/installation/#2-expo-go-app-for-ios-and Solution lourde : installer un émulateur Android
− Ca utilise Android Studio (c’est lourd !)
− Suivre le tuto < ici >, étapes 1 et 2. Passez la question des « adb » (Android Debug Bridge). Ca marche mal sur Mac.
REACT NATIVE – P3 - page 17/104
3 - Créer une première application – v3.2
Situation
On a installé expo CLI : npm install -g expo-cli
Pour utiliser expo CLI : mode d’emploi <ici>
En console : expo –version, etc.
On a installé expo Go sur son téléphone
On va pouvoir commencer à coder et tester notre code.
Première application : https://docs.expo.io/get-started/create-a-new-app/
Création d’une application
# create d’une application expo init my-app-expo cd my-app-expo
Contenu de l’application
REACT NATIVE – P3 - page 19/104 Démarrage du serveur de développement :
# on se place dans le dossier du projet expo start
Bug possible (sur MAC) :
Expo Developer Tools is disconnected from Expo CLI. Use the expo start command to start the CLI again.
Correction (sur MAC) :
brew update
brew install watchman
# nécessite peut-être :
# xcode-select --install
Voir l’application sur son téléphone : scanner le QR code
Ca ouvre une fenêtre dans le navigateur du PC : l’interface Metro Bundler
Starting Metro Bundler
Building JavaScript bundle: finished in 43979ms.
Voir l’application sur Android Studio Bug possible (sur MAC) :
ADB server didn't ACK
C’est difficile à corriger. Il faudrait copier le fichier ~/Library/Android/sdk/platform-tools/adb sur /usr/bin. Mais le dossier /usr/bin est protégé et les procédures habituelles pour contourner ça ne marchent plus sur macOS Big Sur (démarrage cmd+R, csrutil disable, sudo mount -uw/). Ca reste faisable mais très compliqué : <ici>.
On oublie ! On testera uniquement sur le téléphone : ça marche très bien.
Voir l’application sur son navigateur web :
# on se place dans le dossier du projet expo start --web
REACT NATIVE – P3 - page 21/104
Organisation du code v3.2
VS code
On ouvre le dossier my-app-expo dans VS Code.
On y trouve :
Contenu de l’application
C’est un projet node.js classique. On y trouve:
• package.json : fichier de configuration de l’application.
o main : fixe le fichier d’entrée dans l’application. On peut aller voir. Il nous ramène sur App.js (import App from '../../App').
o scripts : liste les scripts utilisables. On peut les voir avec « nmp run-start ».
o dependencies: liste les dépendances de fabrication (expo, react, react-native, etc.).
o devDependencies : liste les dépendances de dév (template Babel) o private: à true, ça empêche la publication du projet
• app.json : un fichier de configuration applicative de l’application avec le nom de l’application, sa version, l’orientation, etc. => <doc ici>. On y reviendra pour le déploiement sur un store Apple ou Google.
• App.js : fichier de code JavaScript. L’entrée de l’application. Forcément App.js avec expo (défini dans le main du package.json).
• assets : un dossier avec des ressources (des images, des polices, etc.)
• node_modules : le dossier des dépendances node.js
• .gitignore : un fichier de configuration git
• .expo, babel et yard : des outils système, fichiers de configuration.
node_modules : npm update
C’est le gros dossier de l’application : 170 M0 pour 30 000 fichiers !!!
Il faut éviter de livrer le fichier node_modules.
On peut toujours le refabriquer en faisant, dans le dossier de l’application : npm update
S’il y a des erreurs, souvent il faut faire un audit et refaire un update : npm audit fix
npm update
REACT NATIVE – P3 - page 23/104
App.js
Le fichier App.js
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function App() { return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="light" />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1,
backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', },
});
App.js, c’est du React.
On y trouve :
des import : c’est du React classique
un composant fonctionnel exporté : App(). C’est du React classique
un objet « styles ». C’est le style CSS (type Android) : c’est du React-native.
On peut voir que le composant fonctionnel App() utilise des composants (format de balise) :
<View> et <Text>, qui sont importés de react-native.
En react-native on n’utilise pas directement de HTML mais des composants qui correspondent à ce qu’on trouve dans le XML Android.
<StatusBar> : c’est un composant qui gère l’affichage de la ligne d’infos du haut du téléphone. Il est importé.
On peut voir que l’objet « styles » est créé à partir du composant StyleSheet importé aussi de react- native.
Noter la présence des « ; » : ils sont facultatifs mais permettent de voir les fins d’instruction JavaScript
Premières modifications du contenu (HTML-XML) Ajoutez 2 points d’exclamation.
L’application est mise à jour automatiquement sur le téléphone (sur MAC avec watchman).
Supprimez la balise fermante </text>
Un message d’erreur apparaît sur le téléphone
Un message d’erreur apparaît dans la fenêtre Metro Bundler Remettez la balise fermante </text>
L’application est mise à jour automatiquement sur le téléphone.
Ajoutez une image avant le texte => <doc ici>
<Image source={require('./assets/favicon.png')}></Image>
Un message d’erreur apparaît sur le téléphone : Can’t find variable : Image
Il faut importer Image comme on a importé Text, View et StyleSheet.
Ajoutez Image dans l’import
import { StyleSheet, Text, View, Image} from 'react-native';
L’application est mise à jour automatiquement sur le téléphone.
Mais l’image n’apparaît pas sur le navigateur Ajoutez du style pour la taille de l’image
style={{height:100,width:100}}
<Image
style={{height:100,width:100}}
source={require('./assets/favicon.png')}
>
</Image>
Syntaxe JSX : le JavaScript entre { }
Pour le style : style = objet JS => on a donc {{ }}
Passer le StatusBar à « light » puis remettez-le à auto <StatusBar style="light" />
Constater l’effet sur la ligne de statut du haut.
REACT NATIVE – P3 - page 25/104 Premières modifications du style (CSS) :
backgroundColor: 'yellow', => <doc ici>
Tout le fond passe en jaune. On pourrait aussi mettre '#ff0' flex: 0.5,
Seule la moitié de l’écran passe en jaune.
justifyContent : 'flex-end', => <doc ici>
Le texte passe en bas alignItems: 'flex-end',
Le texte passe à droite
Outils supplémentaires : snack et doc
Utilisation de Snack
A partir de la documentation du StatusBar :
https://docs.expo.io/versions/v40.0.0/sdk/status-bar/#statusbarstyle On peut cliquer sur “Try this example on Snack »
Ce qui amène sur cette page
On peut aussi aller directement sur son compte expo.io : https://expo.io/
puis sur MonIcone / Snacks, puis sur example.
De là, on peut mettre le code de App.js dans l’exemple et le tester :
Soit en web
Soit avec My Device
Pour l’image, on utilise cette image :
source='http://bliaudet.free.fr/react-native/assets/2.png
REACT NATIVE – P3 - page 27/104 Références React-native :
Générales :
− https://docs.expo.io/bare/exploring-bare-workflow/
− https://docs.expo.io/introduction/walkthrough/
Publier et déployer sur App Store et Google Play Store
− https://docs.expo.io/introduction/walkthrough/#building-and-deploying
− build
− Application loader Première application
− https://docs.expo.io/bare/hello-world/ :
Synthèse des commandes, du code et de l’architecture Commandes
# installation ou mise à jour de expo-cli npm install -g expo-cli
# ou bien
npm install expo-cli --global
# affichage de la version expo –-version
expo -V
# create d’une application expo init my-app-expo cd my-app-expo
## démarrage du serveur expo start
# voir l’application sur son navigateur expo start –web
# mise à jour du dossier node_modules npm update
nmp audit fix npm update
Code App.js :
import { StyleSheet, Text, View, Image} from 'react-native';
<Image
style={{height:100,width:100}}
source={require('./assets/favicon.png')}
>
</Image>
const styles = StyleSheet.create({
container: { flex: 0.5,
backgroundColor: 'yellow', alignItems: 'flex-end', justifyContent: 'flex-end', },
});
REACT NATIVE – P3 - page 29/104 Contenu de l’application
C’est un projet node.js classique. On y trouve:
• package.json : fichier de configuration de l’application.
o main : fixe le fichier d’entrée dans l’application. On peut aller voir. Il nous ramène sur App.js (import App from '../../App').
o scripts : liste les scripts utilisables. On peut les voir avec « nmp run-start ».
o dependencies: liste les dépendances de fabrication (expo, react, react-native, etc.).
o devDependencies : liste les dépendances de dév (template Babel) o private: à true, ça empêche la publication du projet
• app.json : un fichier de configuration applicative de l’application avec le nom de l’application, sa version, l’orientation, etc. => <doc ici>. On y reviendra pour le déploiement sur un store Apple ou Google.
• App.js : fichier de code JavaScript. L’entrée de l’application. Forcément App.js avec expo (défini dans le main du package.json).
• assets : un dossier avec des ressources (des images, des polices, etc.)
• node_modules : le dossier des dépendances node.js
• .gitignore : un fichier de configuration git
• .expo, babel et yard : des outils système, fichiers de configuration.
4 - Créer une première architecture
Installation
Par copie de « my-app-expo »
Sortez le dossier node_modules de « my-app-expo »
Faites une copie du dossier « my-app-expo » pour garder l’original Appelez cette copie « my-app-expo-v2 »
Remettez le dossier node_modules dans « my-app-expo »
cd my-app-expo-v2 npm update
Faites ce que vous dit nmp
Par création de « my-app-expo 2 »
On peut aussi créer my-app-expo-v2 en passant la commande : expo init my-app-expo-v2 :
expo init my-app-expo-v2
REACT NATIVE – P3 - page 31/104
Mise en place d’une première architecture Principe
Notre fichier App fait office de main.
On va limiter son action à récupérer un composant qu’on va écrire.
Créations de nouveaux dossiers
containers : ce sont seront des views contenant des widgets, des composants de l’écran.
components : ce seront nos composants React utilisés dans nos containers.
constants : pour les constantes styles : pour les styles
mkdir containers components constants styles
Pour le moment on ne va utiliser que le dossier containers.
Créations d’un nouveau contenair : Vue
Dans containers, on va créer un composant Vue.
On distingue ce composant en 3 fichiers :
− Vue.js : pour le code JavaScript
− Vue.style.js : pour le style
− index.js : pour faciliter l’appel
Mise en place des composants Vue.js
import React from 'react';
import {Text, View} from 'react-native';
import './Vue.style' const Vue = () => ( <View>
<Text>Ma nouvelle vue !!!</Text>
</View>
)
export default Vue
• On utilise une fonction fléchée.
• On utilise une View et un Text. La View sert de regroupement. Elle permettra de styler de façon plus adaptée.
• On importe « react » pour le « render() » caché, « react-native » pour les composants, et notre style.
• A ce stade, la Vue n’est pas stylée.
index.js
Le fichier index.js permettra qu’on importe uniquement le dossier Vue pour utiliser le composant Vue. Il contient le code suivant :
export {default} from './Vue'
On exporte le contenu de ./Vue.js
Ca permettra d’importer containers/Vue : ça va chercher le fichier index par défaut et récupère donc le fichier Vue.js.
REACT NATIVE – P3 - page 33/104 Adaptation du fichier App.js
App.js contient le code suivant :
import React from 'react';
import Vue from './containers/Vue';
const App = () => <Vue />
export default App
− On importe le dossier Vue qui donne accès au composant Vue via l’index.js.
− On pourrait se passer de l’index.js et importer ./containers/Vue/Vue.
− Le composant App est codée sous la forme d’une fonction fléchée. Il utilise uniquement un composant Vue.
− On pourrait écrire une fonction classique :
export default function App() { return (
<Vue></Vue>
);
}
− Ou une classe
export default class App extends React.Component { render() {
return (
<Vue></Vue>
) } } Test du code
On teste le code à ce stade.
Mise en place du style Vue.style.js – version 1
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
Vue: {
flex: 0.5,
backgroundColor: '#ff0', justifyContent: 'center', },
})
export default styles
A noter le nom du style = Vue : même nom que le composant.
Vue.js
import React from 'react';
import {Text, View} from 'react-native';
import styles from './Vue.styles' const Vue = () => (
<View style={styles.Vue}>
<Text>Ma nouvelle vue !!!</Text>
</View>
)
export default Vue
A noter le nom du style = style.Vue : même nom que le composant.
Test du code
On teste le code à ce stade.
REACT NATIVE – P3 - page 35/104 Vue.style.js – version 2
• On définit plusieurs styles.
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
Vue: {
flex: 0.5,
backgroundColor: '#ff0', justifyContent: 'center', },
Style2: { flex: 1,
backgroundColor: 'pink', justifyContent: 'flex-end', alignItems: 'flex-end', },
Titre: {
textAlign: 'center', fontFamily : 'cursive',
// fontFamily: 'monospace, cursivee, serif, sans-serif, arial', fontSize: 30,
}, })
export default styles Prise en compte des styles dans la Vue
const Vue = () => (
<View style={styles.Vue}>
<Text style={styles.Titre}>Ma nouvelle vue !!!</Text>
</View>
Test du code
On teste le code à ce stade.
On change Vue par Style2
Bilan UML du code
REACT NATIVE – P3 - page 37/104
Synthèse des commandes, du code et de l’architecture Commandes
# création d’une nouvelle application
# on peut aussi dupliquer la précédente expo init my-app-expo-v2
# creation de dossiers et de fichiers - containers
- Vue.js,
- Vue.style.js, - index.js
- components - constants - styles
Code App.js :
import React from 'react';
import Vue from './containers/Vue';
const App = () => <Vue />
export default App
index.js :
export {default} from './Vue'
Vue.js :
import React from 'react';
import {Text, View} from 'react-native';
import styles from './Vue.styles' const Vue = () => (
<View style={styles.Vue}>
<Text>Ma nouvelle vue !!!</Text>
</View>
)
export default Vue
Vue.style.js :
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
Vue: {
flex: 0.5,
backgroundColor: '#ff0', justifyContent: 'center', },
Titre: {
textAlign: 'center', fontFamily : 'cursive',
// fontFamily: 'monospace, cursivee, serif, sans-serif, arial', fontSize: 30,
}, })
export default styles
5 - API Reference expo : https://docs.expo.io/versions/latest/
Deux types d’API :
− React Native
− Expo SDK API React Native
Elle donne accès aux composants de l’interface utilisateur : View, Text, TextInput, Button, etc.
Elle propose des codes d’exemples.
On peut tester ces codes :
− Dupliquer my-app-expo et nommer le test-API
− Remplacer le contenu de App.js par le code proposé
− Tester le code : expo start –web et dans le téléphone.
Expo SDK
Elle donne accès à des API plus ou moins complexes. Gestion des polices, des sons, des vidéos, des assets.
On peut souvent tester les codes sur Snack :
− On visualise le code
− On peut afficher le résultat avec l’onglet « web ». Ca ne s’affiche pas toujours bien.
− On peut afficher le résultat sur son téléphone avec l’onglet « My Device » et le QR Code.
Ca s’affiche en général mieux.
− On peut aussi remplacer le contenu de App.js de test-API par le code proposé. Il faut parfois mettre à jour node_modules.
REACT NATIVE – P3 - page 39/104
ETAPE 2
6 – Application « twitterapp »
1-Structure : main et App
On repart de l’état précédent: « my-app-expo-v2 »
On fait une copie (en retirant le dossier node_modules) et on la renomme en « twitterapp ».
On change la Vue et on l’appelle Main : faire toute les mises à jour nécessaires : dans le dossier Vue (désormais Main).
Vérifier que tout marche comme avant.
2-Création d’un tableau de tweets v4.1
Dans le dossier « constants », on crée un fichier « tweets.js » On y place le code suivant :
const tweets = [ {
_id:0,
date:'1/03/2021' username:'toto'
tweet:'Hello World - 1er tweet',
avatar:'http://bliaudet.free.fr/react-native/assets/0.png';
}, ]
export default tweets
On ajoute 3 autres tweets : username : React Native, React puis Laravel. Les avatars sont en 1, 2 et 3.png.
L’_id nous sert d’identifiant. On met un _id par convention.
Le numéro du fichier avatar correspond au numéro du tweet par convention.
3-Affichage d’un tweet
Main.js v4.2
On affiche le tweet dans le composant Main.
Pour ça on importe le tweet, puis on récupère les éléments dans des composants <Text>
Dans les <Text>, le JavaScript est en JSX : entre { }
import tweets from '../../constants/tweets' const Main = () => (
<View style={styles.Main}>
<Text>{tweets[0].username}</Text>
<Text>{tweets[0].tweet}</Text>
<Text>{tweets[0].avatar}</Text> {/* format texte pour l’ url*/}
<Text>{tweets[0]._id}</Text>
</View>
)
REACT NATIVE – P3 - page 41/104
4-Gestion de l’image v4.3
Gestion de l’image
On va afficher une image.
On a besoin du composant <Image> de react-native.
import {Text, View, Image} from 'react-native';
On remplace le composant <Text> par le composant <Image> : c’est une balise orpheline.
L’attribut source permet d’accéder au fichier source : on le récupère dans les tweets : on a donc du JSX.
L’attribut style récupère un objet JavaScript en paramètre : on a donc du JSX est des doubles {{ et }}
<Text>{tweets[0].avatar}</Text> {/* format texte pour l’
devient
<Image source={tweets[0].avatar} style={{width:50, height:50}}/>
Il faut mettre un style avec width et height pour que tout fonctionne bien.
Dans la constante tweets, on peut gérer 2 cas :
Soit l’image est sur internet
Soit l’image sera dans notre dossier assets/logos
const tweets = [ {
_id: 0,
avatar: require('../assets/logos/0.png'), },
{
_id: 2,
avatar: 'http://bliaudet.free.fr/react-native/assets/2.png', },
require() permet récuperer l’image.
Il faut mettre les images dans le dossier assets/logos
On teste en changeant le tweet dans le main : un coup le 0, un coup le 2 A noter que l’image 1 est 2 fois plus large que haute.
A ce stade, on à cette situation :
REACT NATIVE – P3 - page 43/104
5-Création d’un composant avec des paramètres v4.4
Principes
Le but : créer un composant Tweet réutilisable avec des paramètres.
Ce composant, on le met dans le dossier « component ».
Ce composant nous permettra d’afficher chaque tweet.
Il aura la même structure que Main :
On peut faire une copie du dossier Main dans le dossier component.
Ensuite on met à jour les noms de fichier et de dossier : on remplace Main par Tweet.
On peut aussi mettre à jour le contenu des fichiers : on remplace Main par Tweet.
On a donc dans components : index.js, Tweet.js, Tweet.styles.js Le but sera d’obtenir ce résultat :
Tweet.js
• Tweet.js va servir à afficher un tweet.
• On lui passe en paramètre : date, tweet, username, avatar
• Il retourne une balise <View> : c’est l’équivalent d’un <div> html
const Tweet = ({ date, tweet, username, avatar}) => ( <View style={styles.Tweet}>
<Image
source={avatar}
style={{width:50, height:50}}
/>
<Text style={styles.date}>{date}</Text>
<Text style={styles.username}>{username}</Text>
<Text style={styles.tweet}>{tweet}</Text>
</View>
const Tweet = ({ date, tweet, username, avatar}) => ( Tweet.styles.js
• Pour le moment, Tweet.styles est vide.
const styles = StyleSheet.create({
Tweet: { // vide },
})
REACT NATIVE – P3 - page 45/104 Main.js
• Le main utilise 2 Tweet. Notez la présence de variable classiques : n1 et n2
let n0=1, n1=2
const Main = () => (
<View style={styles.Main}>
<Tweet
date={tweets[n0].date}
username={tweets[n0].username}
avatar={tweets[n0].avatar}
tweet={tweets[n0].tweet}
/>
<Tweet
date={tweets[n1].date}
username={tweets[n1].username}
avatar={tweets[n1].avatar}
tweet={tweets[n1].tweet}
/>
</View>
) }
• Il faudra mettre à jour Main.styles pour avoir l’affichage non centré.
• Changez les valeurs de n1 et n2.
• Mettez les 4 tweets.
6-Bilan UML du code
On peut distinguer entre les Classes avec un render() et les données (comme le tweets).
On met dans l’ordre : React, styles et View, qui sont les plus communes.
On peut mettre le constructeur avec les props
REACT NATIVE – P3 - page 47/104
7-Dossier style : nommer ses couleurs v4.5
Dans le dossier style de notre application, on va mettre un fichier « variables.js ».
Dans ce fichier, on définit nos codes couleurs.
Pour ça, on crée une const colors qu’on exporte et on y met des couleurs.
const colors = {
primary: '#10dffd' // le bleu twitter lightblue : ‘lightblue’,
white: white, blue: '#9ad4ff' darkblue: '#4f34ff' }
export default colors
Ensuite, dans Main.style.js, on importe ce fichier et on utilise la variable « colors » :
import colors from '../../styles/variables' backgroundColor:colors.lightblue
8-Mise en page type flex
Structure : les view comme des div
On veut présenter nos tweets en mettant le texte à côté de l’image et en alignant la date et le username :
Pour ça, on commence par structurer le tweet en ajoutant des « view » pour chacune des parties.
La « view » est comme une « div » HTML
On associe la view à un style.
REACT NATIVE – P3 - page 49/104
On obtient ce code :
<View style={styles.Tweet}>
<View style={styles.left}>
<Image
source={avatar}
style={{width:50, height:50}}
/>
</View>
<View style={styles.right}>
<View styles={styles.top}>
<Text style={styles.date}>{date}</Text>
<Text style={styles.username}>{username}</Text>
</View>
<View style={styles.bottom}>
<Text style={styles.tweet}>{tweet}</Text>
</View>
</View>
</View>
Notez les styles.left, styles.right, styles.bottom, styles.top en plus du styles.Tweet
Structure : les view comme des div
D’abord on met le texte à droite de l’image et on aligne la date et le username
C’est une logique de flex HTML
Dans Tweet.styles, on un une flexDirection à ‘row’ :
Tweet: {
flexDirection: 'row', },
top: {
flexDirection: 'row', },
Documentation flex react native : https://reactnative.dev/docs/flexbox Petits tests
On met un couleur white sous le texte On encadre la partie de l’image On met un espace à droite de la date
left: {
borderWidth:1, borderColor:'red', }
right {
borderWidth:1, borderColor:'green'
backgroundColor:colors.white, },
date: {
marginRight: 10, }
On voit les blocs apparaître, comme en HTML. Ca permettra de les styler comme on veut.
Documentation react native : https://reactnative.dev/docs/stylesheet
REACT NATIVE – P3 - page 51/104 Gestion des passages à la ligne :
On allonge un tweet :
tweet: 'React est sur twitter. On met un tweet long pour voir comment il s\'affiche quand ça débord. Regardez bien !',
On constate que sur le telephone, c’est coupé.
C’est la partie « right » qui pose problème : pour éviter ça, on peut faire :
right: { flex:1,
C’est du CSS-flex : right est un enfant de Tweet qui est flexé (flexDirection). Du coup, en précisant flex :1 sur un enfant, il s’étale sur toute la place restante et gère les passages à la ligne.
Documentation flex react native : https://reactnative.dev/docs/flexbox Gestion de la taille de l’image
Dans <Image, on supprime :
style={{width:50, height:50}}
Et on remplace par :
source={avatar}
Dans Tweet.styles :
avatar: { width: 50, height: 50, },
Dernières subtilités
• On passe tout le Tweet sur fond blanc (backgroundColor)
• On centre les images (justifyContent)
• On supprime les bordures
• On met une bordure blue de 0.5 (borderWidth, borderColor) sur les Tweet et une marge en bas (marginBottom) de 4
• On met une marge à gauche (marginLeft) de 2 sur le texte.
• On passe le texte du tweet en gras (fontWeight)
• On décale de 4 l’image à gauche (marginLeft)
• On ajoute un @ devant le username et on affiche le username et l’@ en primay.
REACT NATIVE – P3 - page 53/104
9-Afficher tous les tweets Version sans boucle
const Main = () => (
<View style={styles.Main}>
<Tweet
date={tweets[0].date}
username={tweets[0].username}
avatar={tweets[0].avatar}
tweet={tweets[0].tweet}
/>
<Tweet
date={tweets[1].date}
username={tweets[1].username}
avatar={tweets[1].avatar}
tweet={tweets[1].tweet}
/>
<Tweet
date={tweets[2].date}
username={tweets[2].username}
avatar={tweets[2].avatar}
tweet={tweets[2].tweet}
/>
<Tweet
date={tweets[3].date}
username={tweets[3].username}
avatar={tweets[3].avatar}
tweet={tweets[3].tweet}
/>
</View>
)
On peut avoir une erreur :
Unchecked runtime.lastError: The message port closed before a response was received
Ce n’est pas grave : ça peut être dû à l’installation du navigateur.
REACT NATIVE – P3 - page 55/104
Parenthèse : livraisons légères
Objectif
• Livrer le projet minimum pour pouvoir le réinstaller.
Dossiers et fichiers à supprimer
• Le dossier nodes-modules
• Le dossier .expo/web/cache
• Les 2 fichiers « lock »
Réinstallation
>npm update --force
>expo start –web ça marche !
7 – Boucle pour afficher tous les tweets v4.6
Rappels de syntaxe sur les boucles
Boucle « for » : rappel
for(let i=0 ; i< tab.length ; i++) console.log(tab[i]) ; boucle « for key in » : rappel
• La boucle « for key in » permet de récupérer chaque élément d’une structure ou d’un tableau dans une variable.
for( key in tab) console.log(tab[key]) ;
• Exemple avec une structure :
var person = {fname:"John", lname:"Doe", age:25};
var text = "";
var x;
for (x in person) {
text += person[x] + " ";
}
// text vaut : "John Doe 25"
https://www.w3schools.com/jsref/jsref_forin.asp
méthode forEach() : rappel
• La méthode forEach() permet d'exécuter une fonction sur chaque élément du tableau. On code la fonction directement dans le forEach :
const tab = ['a', 'b', 'c'];
tab.forEach(function(element) { console.log(element);
});
• On peut aussi passer une fonction en paramètre et définir la fonction ailleurs.
const tab = ['a', 'b', 'c'];
tab.forEach(maFonction(element));
function maFonction(element){
console.log(element);
REACT NATIVE – P3 - page 57/104 méthode map() : rappel
• La méthode map() retourne un tableau avec les valeurs retournées par le fonction.
const tab = [1, 2, 3, 4]
const tabCarre = tab.map(function (elt) { return elt*elt
})
console.log(tabCarre) // [ 1, 4, 9, 16 ]
• https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/map const personnes=[{id: 1, nom:'toto'}, {id: 2, nom: 'titi'}]
tabNoms = personnes.map(function (personne) { return personne.nom
})
console.log(tabNoms) // [ 'toto', 'titi' ]
map et index
const tab = [1, 2, 3, 4]
tab.map(function (elt, index) {
console.log('tabCarre['+index+']='+elt+' -> carré='+elt*elt) })
max et fonction fléchée
const tabCarre = tab.map(function (elt) { return elt*elt
})
devient :
const tabCarre = tab.map(elt => { return elt*elt
})
devient :
const tabCarre = tab.map(elt => elt*elt) méthode filter() : rappel
• La méthode filter() retourne un tableau avec uniquement certaines valeurs du tableau de départ.
const entiers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const pairs = entiers.filter(entier => entier%2 == 0);
console.log(pairs); // [2, 4, 6, 8, 10];
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter Bien distinguer un map d’un forEach
> tweets=[1, 3, 4, 5]
> tweets.forEach(function(elt){return elt}) undefined
> tweets.map(function(elt){return elt}) [ 1, 3, 4, 5 ]
Afficher tous les tweets : version compacte Solution – 1 – compact mais avec warning
• Version ultra-compacte avec un warning : const Main = () => (
<View style={styles.Main}>
{ tweets.map( tweet => (<Tweet {...tweet} />))}
</View>
)
On a un warning :
index.js:1 Warning: Each child in a list should have a unique "key" prop.
On y reviendra.
Principe du spread operator ici : …
Chaque attribut de l’objet « tweet » va prendre la place des attributs de la balise Tweet.
let obj = { foo: 'bar', x: 42 }
<Composant foo='bar' x=42 />
<Composant {...ojb } /> // les deux sont identiques La balise Tweet est définie ainsi :
const Tweet = ({ date, tweet, username, avatar}) => (
On a donc 4 attributs : date, tweet, username et avatar.
• L’objet tweet est définie ainsi : {
_id: 0,
date: '1/03/2021', username: 'toto',
tweet: 'Hello World - 1er tweet',
avatar: require('../assets/logos/0.png'), }
• On écrit donc :
<Tweet {...tweet} />
REACT NATIVE – P3 - page 59/104 Rappels sur Spread operator : …
• L’opérateur « spread » s’applique à un tableau : il renvoie la liste des éléments du tableau séparés par des virgules :
...[1, 2, 3] vaut 1, 2, 3
...['1', '2', '3'] vaut '1', '2', '3'
...[{a :1, b :2}', '3', 10] vaut {a :1, b :2}', '3', 10
1er usage : sur un tableau
• pour créer un tableau à partir d’un autre tableau en ajoutant un ou plusieurs éléments : const colors = ['red', 'green', 'blue']
const colors2 = ['yellow', ...colors, 'pink']
2ème usage : sur un objet Copie par référence
let obj1 = { foo: 'bar', x: 42 }
let obj2 = obj1 // copie par référence obj1.x=50
console.log(obj2.x) // vaut 50 Duplication réelle
let obj3 = { ...obj1 };
obj1.x=100
console.log(obj3.x) // vaut 50
3ème usage : sur une fonction
Pour passer des paramètres à une fonction : function test(a, b, c){
console.log('a: ',a) console.log('b: ',b) console.log('c: ',c) }
test(...colors)
4ème usage : dans React, sur un composant : Pour passer des paramètres à un composant :
let obj = { foo: 'bar', x: 42 }
<Composant foo='bar' x=42 />
<Composant {...ojb } /> // les deux sont identiques Références :
• https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
Solution – 2 – compacte, sans warning (la bonne !)
• Version ultra-compacte sans warning : const Main = () => (
<View style={styles.Main}>
{ tweets.map(
tweet => (<Tweet key={tweet._id} {...tweet} />) )}
</View>
)
Dans le composant Tweet, on ajoute un attribut key qui sert d’identifiant : la valeur qu’il reçoit doit être différente pour tous les composants Tweet.
• Une autre solution est de récupérer l’index de chaque élément mappé : const Main = () => (
<View style={styles.Main}>
{ tweets.map(
(tweet, index) => (<Tweet key={index} {...tweet} />) )}
</View>
)
REACT NATIVE – P3 - page 61/104 Solution – 3 – on ajoute des filtres
• On filtre sur le nom de l’utilisateur : const Main = () => (
<View style={styles.Main}>
{ tweets
.filter(tweet => tweet.username.includes('a'))
.map( tweet => (<Tweet key={tweet._id} {...tweet} />))}
</View>
)
On commence par filtrer notre tableau de tweets : tweets.filter()
Ca retourne un tableau qu’on « mappe ».
On peut tout enchainer à la suite !
Solution – 4 – exemple d’ajout d’affichage en plus des tweets
• On affiche des « trucs » en plus : la liste de tous les utilisateurs, le nom d’un utilisateur, l’id de l’utilisateur affiché :
const Main = () => (
<View style={styles.Main}>
{ tweets
.filter(tweet => tweet.username.includes('a')) .map( tweet => (<div>
{tweets.map(tweet => '('+tweet.username+')')}
<br/>{tweets.filter(tweet =>
tweet.username=='toto')[0].username}
<br/>{tweet._id}
<Tweet key={tweet._id} {...tweet} />
</div>))}
</View>
)
REACT NATIVE – P3 - page 63/104 Solution – 5 – version sans spread
// version Tweet destructuré const Main = () => (
<View style={styles.Main}>
{
tweets.map( tweet => ( <Tweet
key={tweet._id}
date={tweet.date}
username={tweet.username}
avatar={tweet.avatar}
tweet={tweet.tweet}
/>
)) }
</View>
)
// version Tweet et tweet destructurés const Main = () => (
<View style={styles.Main}>
{
tweets.map( ({_id, date, username, avatar, tweet}) => ( <Tweet
key={_id}
date={date}
username={username}
avatar={avatar}
tweet={tweet}
/>
)) }
</View>
)
*/