React Native : introduction

Ecole Nationale Supérieure de Cognitique

Baptiste Pesquet

Sommaire

  • L’écosystème mobile
  • Premiers pas avec React Native
  • Anatomie d’une application React Native
  • La notion de composant

L’écosystème mobile

Smartphone platform market share

Market share evolution 2015-2019

Mobile OS Fragmentation

Développement natif

Création d’applications en utilisant la technologie prévue par le concepteur de l’OS.

  • Android : Java
  • IOS : Objective-C ou Swift

Ces technologies sont incompatibles.

Avantages

  • Accès à l’intégralité des fonctionnalités matérielles et logicielles du terminal mobile.
  • Performances optimales.

Inconvénient (majeur !)

Nécessité de créer puis de faire évoluer une application pour chaque environnement.

Solutions hybrides

Création d’applications mobiles compatibles avec plusieurs OS mobiles grâce à un framework dédié.

Une application hybride est une application web qui s’exécute à l’intérieur d’un navigateur.

Exemples : Apache Cordova, Ionic

Avantages

  • Fonctionnalités et performances proches de celles d’une application native.
  • Economies de ressources pour créer l’application.
  • Une seule base de code : maintenance et évolution facilitées.

Inconvénients

  • Impossible d’accéder à certaines fonctionnalités matérielles ou logicielles spécifiques.
  • Look’n’feel non natif.
  • Mauvaises performances dans certains scenarii.

Développement natif multi-plateformes

Création d’applications mobiles compatibles avec plusieurs OS mobiles grâce à un framework dédié.

Le framework encapsule les véritables composants natifs de l’OS.

Exemples : React Native, Weex, Xamarin

Le meilleur des deux mondes ?

Combine les avantages du natif (look’n’feel, performances) et de l’hybride (une seule base de code).

Limite potentielle : le support de l’OS dépend entièrement du framework.

Premiers pas avec React Native

React Native

Framework créé par Facebook, open source depuis 2015.

Déclinaison mobile du framework JavaScript React.

React logo

Expo

Framework pour faciliter la création et le déploiement d’applications React Native.

Expo logo

  • Expo CLI : outil en ligne de commande pour le développement local.
  • Expo client : application mobile à installer sur le terminal cible pour le déploiement.

Création d’une application

# Install expo-cli globally
# (Node.js and Git are prerequisites)
npm install -g expo-cli

# Create a new app in the my-new-project subfolder
# Use managed TypeScript template
expo init my-new-project -t expo-template-blank-typescript
  • Workflow managé : projet entièrement géré par Expo (plus simple).

  • Workflow bare : plus proche d’un projet React Native pur.

Contenu du répertoire créé

Arborescence React Native

Déploiement de l’application

cd my-new-project # move into project directory
npm start # Or 'expo start'

Ensuite, scan du QR Code depuis l’application Expo (Android) ou l’appareil photo du smartphone (iOS).

Expo QR Code

Détails sur le déploiement

  • L’application est hébergée sur un serveur web local.
  • Expo s’y connecte pour la récupérer puis la lancer.
  • Une interface web de gestion s’affiche.

Expo Management

Rechargement dynamique

Live Reload

Connexion au serveur Expo

L’application mobile Expo client doit accéder au serveur web de la machine de développement pour pouvoir lancer l’application RN.

Il existe plusieurs modes de connexion :

  • LAN : utilisation du réseau Wifi local. Peut poser problème dans certains environnements Wifi sécurisés.
  • Tunnel : création d’un tunnel avec ngrok pour accéder au serveur local via le web. Nécessite que le terminal mobile dispose d’un accès internet.

Utilisation d’un émulateur

  • Alternative à l’emploi d’un terminal mobile pour tester l’application RN.
  • Nécessite l’installation de XCode (iOS) ou Android Studio sur le machine de développement.
  • Documentation : iOS | Android.

Expo emulator

Anatomie d’une application React Native

Le fichier de configuration app.json

{
  "expo": {
    "name": "My New Project",
    "slug": "my-new-project",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "updates": {
      "fallbackToCacheTimeout": 0
    },
    "assetBundlePatterns": ["**/*"],
    "ios": {
      "supportsTablet": true
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#FFFFFF"
      }
    },
    "web": {
      "favicon": "./assets/favicon.png"
    }
  }
}

Le fichier package.json

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "expo": "~40.0.0",
    "expo-status-bar": "~1.0.3",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
    "react-native-web": "~0.13.12"
  },
  "devDependencies": {
    "@babel/core": "~7.9.0",
    "@types/react": "~16.9.35",
    "@types/react-dom": "~16.9.8",
    "@types/react-native": "~0.63.2",
    "typescript": "~4.0.0"
  },
  "private": true
}

Le fichier principal App.tsx

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.tsx to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

Les formats JSX et TSX

  • Syntaxe introduite pour le framework web React.
  • Permet de décrire une UI en intégrant balisage et logique applicative.
  • TSX : équivalent de JSX avec support de TypeScript.
// JSX for React (web)
const name = "Clarisse Agbegnenou";
const element = <h1>Hello, {name}</h1>;
// JSX for React Native (mobile)
const a = <View />;
const b = (
  <View foo="hello" bar={baz}>
    <Text>42</Text>
  </View>
);

La notion de composant

Définition

  • Les composants sont les blocs de base d’une application React (Native).

  • Ils permettent de créer une UI sous forme déclarative par assemblage de composants.

  • Ils doivent comporter une fonction qui définit leur rendu visuel.

Composants fonctions

  • La valeur de retour de la fonction définit le rendu.
  • Syntaxe la plus concise, pratique pour les composants simples.
import React from "react";
import { Text } from "react-native";

const Cat = () => {
  const name = "Maru";
  return <Text>Hello, I am {name}!</Text>;
};

export default Cat;

Composants classes

  • La méthode render() définit le rendu.
  • Syntaxe à privilégier pour les composants complexes.
import React from "react";
import { Text } from "react-native";

class Cat extends React.Component {
  render() {
    const name = "Maru";
    return <Text>Hello, I am {name}!</Text>;
  }
}

export default Cat;

Propriétés (props) d’un composant

Caractéristiques définies au moment de la création, modifiables uniquement par le composant parent (démo).

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

class Greeting extends Component {
  // Component has a name property which is of type string
  constructor(public props: { name: string }) {
    super(props);
  }
  render() {
    return <Text>Hello {this.props.name}!</Text>;
  }
}

export default class LotsOfGreetings extends Component {
  render() {
    return (
      <View style={{ alignItems: "center" }}>
        <Greeting name="John" />
        <Greeting name="Paul" />
        <Greeting name="Jones" />
      </View>
    );
  }
}

Etat (state) d’un composant

Etat interne (données) d’un composant, susceptible de changer au cours du temps (mutable). Modifié uniquement via setState() (démo).

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

interface CoounterState {
  count: number;
}

class Counter extends Component<{}, CoounterState> {
  constructor(public props: { color: string; size: number }) {
    super(props);
    this.state = { count: 0 };
    setInterval(() => {
      this.setState({ count: this.state.count + 1 });
    }, 1000);
  }

  render() {
    const { count } = this.state;
    const { color, size } = this.props;

    return <Text style={{ color, fontSize: size }}>{count}</Text>;
  }
}

export default class CounterApp extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Counter color="red" size={50} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

Composants de base

React Native core components

Composants d’interface utilisateur

React native UI components