Plongez dans React Native pour le développement Android

Publié: 2022-03-11

Il y a quelques années, un de mes collègues m'a parlé de React Native. J'étais très sceptique. J'ai soutenu qu'il s'agissait simplement d'un autre cadre multiplateforme qui ne fonctionnerait jamais dans la vraie vie - je ne savais pas à quel point je me trompais.

Les années ont passé et les compétences de React Native sont devenues très demandées. Comme cela faisait un moment que j'avais appris quelque chose de nouveau, je me suis dit pourquoi ne pas essayer ? Aujourd'hui, je suis un grand défenseur de React Native.

Les inconvénients:

  • Vous ne pouvez plus utiliser Android Studio
  • React Native ne peut pas être utilisé pour toutes les applications ou fonctionnalités
  • React Native est un nouveau framework et les mises à jour peuvent avoir un effet négatif sur votre base de code actuelle
  • JavaScript n'est pas un langage strictement typé
  • React Native nécessite un moteur JavaScript pour fonctionner, ce qui peut le rendre moins performant

Avantages:

  • Facile à apprendre
  • Une base de code partagée entre les applications Android et iOS, avec seulement des ajustements mineurs nécessaires pour correspondre aux expériences de la plate-forme
  • Rechargement en direct et à chaud, ce qui signifie qu'il n'y a plus de temps de construction infinis
  • Composants natifs pour les deux plates-formes
  • Amélioration constante
  • Communauté en pleine croissance
  • Un grand nombre de bibliothèques
  • Expo supprime le besoin de posséder un Mac pour développer pour iOS
  • Réduction des ressources en main-d'œuvre - bien que vous ayez encore besoin d'un développement natif Android/iOS, cela sera peu fréquent.

Je peux continuer encore et encore, mais arrêtons-nous ici et passons au sujet de cet article de blog. Dans cet article, je vais créer quatre applications Android alimentées par React Native :

  1. Un compteur de base avec des boutons pour incrémenter et décrémenter le compteur
  2. Une application pour rechercher le subreddit r/pics
  3. Une page de connexion générique
  4. Une application pour parcourir le subreddit r/pics

EDI

Comme je l'ai mentionné ci-dessus, il n'y a aucun moyen d'utiliser Android Studio pour le développement React Native. Nous avons besoin d'un remplaçant. React Native peut probablement être développé dans n'importe quel éditeur de texte moderne disponible (Atom, VS Code, Sublime Text, Brackets, etc.) mais puisque nous venons avec l'expérience Android Studio, mon préféré est WebStorm qui est construit par la même société. Bien que WebStorm soit une application payante (129 $ par an), vous pouvez en installer la version Early Access. La version EAP de WebStorm est gratuite et assez stable. Si vous préférez un éditeur entièrement gratuit, optez pour VS Code. Microsoft a même développé un incroyable plugin React Native pour cela et cela fonctionne très bien.

Création d'un nouveau projet

Prérequis : Android SDK, Node et React Native installés sur votre ordinateur.

Il existe deux façons de créer un nouveau projet React Native.

  1. La voie conventionnelle. Soit avec l'interface graphique WebStorm, soit avec la commande du terminal : react-native init AwesomeToptalProject
  2. Manière plus simple "Créer une application native React". create-react-native-app AwesomeToptalProject

Si vous utilisez create-react-native-app , le projet créé sera démarré avec expo. Je n'entrerai pas dans les détails, mais en gros, cela signifie que vous n'avez pas besoin d'installer Xcode pour exécuter l'application sur iOS. Il est également plus facile d'avoir le client toujours à jour grâce à la fonctionnalité d'expo.io et à certaines autres fonctionnalités. Mais vous ne pouvez pas ajouter de code natif. Ainsi, si vous développez une fonctionnalité spécifique, vous devrez peut-être éjecter une application d'expo et utiliser un projet React Native à la place.

Je vais utiliser la première méthode.

Exécutons le projet. Tout d'abord, ouvrez un émulateur ou connectez l'appareil. Si vous avez créé le projet avec WebStorm GUI, tout ce que vous avez à faire est de choisir une configuration. Dans le coin supérieur droit de WebStorm, cliquez sur le menu déroulant à gauche du bouton Exécuter, choisissez Android, puis cliquez sur Exécuter ou Déboguer. Si vous avez créé le projet avec Terminal, vous pouvez soit ajouter une nouvelle configuration React Native, soit l'exécuter à l'aide de Terminal :

 cd AwesomeToptalProject react-native run-android

Si tout s'est bien passé, vous serez accueilli par l'écran suivant :

Mise en page générée

Structure et configuration de base

Les éléments notables à l'intérieur du projet sont :

  • android - Projet Android Studio préconfiguré avec le support React Native.
  • ios - Projet Xcode préconfiguré avec le support React Native.
  • node_modules - Un dossier contenant le framework React Native et d'autres bibliothèques Javascript.
  • index.js - Un point d'entrée pour notre application.
  • App.js - Composant initial chargé.

Créons un dossier "src" à l'intérieur de la racine du projet et déplaçons-y App.js. Vous devrez mettre à jour les importations index.js pour qu'elles correspondent au nouvel emplacement App.js.

 import App from './src/App';

Supprimez tout dans App.js et collez ce code :

 import React from 'react'; import {Text} from 'react-native'; export default class App extends React.Component { render() { return ( <Text>Hello TopTal</Text> ); } }

Le code que nous avons collé est assez simple. Nous avons créé une classe App (enfant de React.Component ) qui remplace la méthode render() et renvoie le composant Text . React.Component est la classe de base pour créer une interface utilisateur à l'aide de JSX. Le modificateur export default rend la classe public .

Nous sommes maintenant prêts à commencer à concevoir notre mise en page.

Mise en page avec Flexbox

Flexbox est similaire à LinearLayout , mais Flexbox va bien au-delà des capacités de LinearLayout .

Cet extrait de JSX :

 <View style={{ flex: 1, flexDirection: 'row' }}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD' }}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2' }}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7' }}/> </View>

Rend cette mise en page :

Mise en page générée


Alors que ce XML :

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>

Rendu ceci :

Mise en page générée

Le code JSX vous semble familier, hein ? ! Créons un "dictionnaire" (ou une feuille de triche) pour les mises en page utilisant qui se ressemblent dans JSX et Android XML.

Veuillez noter que les fonctionnalités ne sont pas nécessairement égales. J'essaie d'aider les débutants de React Native à saisir l'idée du système de mise en page dans React Native. Veuillez vous référer au guide officiel pour des informations détaillées.

Considérez cette propriété JSX :

 flex: 1

C'est équivalent à ça :

 android:layout_width="match_parent" android:layout_height="match_parent"

Cet extrait de JSX :

 <View style={{flex: 1, flexDirection: 'row'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>

Et ce XML :

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>

Les deux génèrent cette sortie :

Mise en page générée


De même, ce JSX :

 <View style={{flex: 1, flexDirection: 'column'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>

Et ce XML :

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>

Générez ceci :

Mise en page générée


Pour obtenir la bonne position à l'intérieur du conteneur, nous utiliserons le plus souvent une combinaison de flexDirection , alignItems et justifyContent .

Ce JSX :

 <View style={{flex: 1, flexDirection: 'column', alignItems: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>

Et ce XML :

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>

Produira cette mise en page :

Mise en page générée


Ce JSX :

 <View style={{flex: 1, flexDirection: 'column', justifyContent: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>

Et ce XML

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>

Produira cette mise en page :

Mise en page générée


Ce JSX :

 <View style={{flex: 1, flexDirection: 'row', justifyContent: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>

Et ce XML :

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>

Produira cette mise en page :

Mise en page générée


Ce JSX :

 <View style={{flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>

et ce XML :

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>

Produira cette mise en page :

Mise en page générée


Leçon à retenir : si nous avons flexDirection: row', alignItems works on Y axis and JustifyContent works on X axis. Everything is mirrored for works on X axis. Everything is mirrored for flexDirection : column' - justifyContent affecte l'axe Y et alignItems affecte l'axe Y.

JustifierContenu : 'flex-start' gravité="début|gauche"
alignItems : 'flex-start' gravité="début|gauche"
justifieContent : 'flex-end' gravité="fin|droite"
alignItems : 'flex-end' gravité="fin|droite"

Essayez-le vous-même. Définissez la valeur justifyContent sur space-around , space-between et space-evenly .

Gestion de l'état

Pour mettre à jour l'état de l'application, vous allez utiliser la variable d' state de React. Chaque fois que state est mis à jour, render() est invoqué.

Copiez le code ci-dessous dans votre application :

 import React from 'react'; import {Button, Text, View} from 'react-native'; export default class App extends React.Component { /* Initialize state object with variable 'number' set to 0 and variable name with value of empty string */ state = {number: 0}; render() { return ( <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', flex: 1, padding: 20 }}> <Button title='Decrement' color='#e57373' onPress={() => this.decrement()}/> <Text> {/* Text will be automatically updated whenever state.number has changed value */} Value = {this.state.number} </Text> <Button title='Increment' color='#64B5F6' {/* Set listener for click */} onPress={() => this.increment()}/> </View> ); } //Declaration of decrement function decrement() { //To update the state we need invoke this.setState //with new value for variable 'number' this.setState({number: this.state.number - 1}); } increment() { this.setState({number: this.state.number + 1}); } } 
Application de décrémentation finale

Si vous cliquez sur les boutons DECREMENT et INCREMENT, vous verrez que le texte est automatiquement mis à jour pour vous. Il n'est pas nécessaire d'utiliser explicitement textView.setText("Value " + number) .

La fonctionnalité d'état est pratique pour plusieurs raisons :

  • Facilité d'obtention de la valeur : vous savez toujours où et comment obtenir la valeur d'une variable spécifique.
  • Les données ne sont pas liées à des widgets spécifiques.
  • Avoir plusieurs widgets dépendant du changement de valeur commun.

Créer une application de recherche pour /r/pics

Maintenant que nous maîtrisons les fondamentaux, créons quelque chose d'un peu plus complexe : une application de recherche pour /r/pics. Reddit fournit un point de terminaison d'API JSON simple, nous n'aurons donc pas à faire de quêtes secondaires pour obtenir l'authentification pour que cela fonctionne correctement.

React Native fournit une API Fetch intégrée. Étant donné que la plupart d'entre nous sont probablement habitués à Retrofit et à sa facilité d'utilisation, nous utiliserons axios . Vous pouvez installer axios via une commande de terminal

en utilisant yarn (ma méthode préférée):

yarn add axios

ou en utilisant npm :

npm install axios

Importations:

 import React from 'react'; import { TextInput, View, Text, Image, ActivityIndicator, Platform, StyleSheet } from 'react-native'; import axios from 'axios'; TextInput = EditText, ActivityIndicator = ProgressBar Platform - Platform detecting module StyleSheet - Module for creating stylesheets and moving them away from JSX

Créez la classe :

 export default class App extends React.Component { }

Pour initialiser l'état. Nous aurons besoin de :

  • chargement - Pour afficher une barre de progression.
  • error - Pour montrer si une erreur s'est produite lors d'une demande d'API REST.
  • imgUrl - Pour prévisualiser l'image recherchée.
  • texte - requête de recherche.
 state = {text: '', loading: false, error: null, imgUrl: null};

Ajoutez le code JSX. Nous avons une disposition verticale avec des composants TextInput et Image .

 render() { return ( //Predefined style. See below <View style={styles.containerStyle}> {/* returnKeyType ~ imeOptions onSubmitEditing ~ et.OnEditorActionListener */} <TextInput style={styles.textInputStyle} placeholder="Enter text to search an image" returnKeyType='search' autoFocus={true} onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()}/> {/* Render error Image component if this.state.imgUrl is not equal to null */} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> } </View> ); }

Nouveautés :

 onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> }

La première méthode effectue un travail similaire à EditText avec le composant TextWatcher . Soyons honnêtes, c'est bien plus sympa en React Native.

La deuxième méthode est invoquée lorsque la touche de retour est enfoncée sur le clavier ( et.OnEditorActionListener ) après avoir déclenché searchPicture() .

L'image est rendue lorsque imgUrl n'est pas null ou indéfini puisque l'opérateur '&&' ne vérifie pas un deuxième argument si le premier est déjà faux.

Vous vous demandez peut-être pourquoi this.state.imgUrl est faux. Eh bien, lors de l'utilisation d'opérateurs logiques en JavaScript, tout sauf '' (une chaîne vide), 0 , false , null ou undefined est vrai. Aucun contrôle spécifique n'est nécessaire.

 searchPicture() { //Default state this.setState({loading: true, error: null, imgUrl: null}); axios.get('https://www.reddit.com/r/pics/search.json', { params: { //the get param map restrict_sr: 'on', //search only /r/pics limit: 1, //limit to one search item sort: 'new', //sort by creation date q: this.state.text //our search query } }).then(response => { //promise is resolved and 'then' block is triggered //set state with new values this.setState({ imgUrl: response.data.data.children[0] .data.preview.images[0].source.url, error: null, loading: false }) }).catch(error => {//Some error occurred //set error this.setState({error: error.message, loading: false, imgUrl: null}) }) }

Nous y voilà. L'application devrait maintenant fonctionner comme prévu. Entrez une chaîne de recherche et appuyez sur retour.

Application de recherche finale de reddit

Étant donné que notre application est également prête à afficher ActivityIndicator et les erreurs, nous devons ajouter du code supplémentaire après le composant Image :

 { //Separate method this.renderProgress() } {/* Render error Text component if this.state.error is not equal to null */} { this.state.error && <Text style={{margin: 16, color: 'red'}}> {this.state.error} </Text> }

Vous pouvez également déplacer les composants de rendu en dehors de la méthode render() principale :

 renderProgress() { //If this.state.loading is true //return View containing a progressbar //View takes style array if (this.state.loading === true) { return ( <View style={ [styles.containerStyle, {justifyContent: 'center'}]}> <ActivityIndicator color='#e57373'/> </View> ); } }

Il ne reste plus que des styles. Mettez-les en dehors de la classe App .

 const styles = StyleSheet.create({ containerStyle: { flexDirection: 'column', flex: 1, //Since React Native is cross platform //let's handle both platforms. //Add top margin to fix status bar overlap marginTop: Platform.OS === 'ios' ? 20 : 0, }, textInputStyle: { marginLeft: 16, marginRight: 16, height: Platform.OS === 'ios' ? 30 : undefined } });

Nous pouvons maintenant ajouter quelques ajustements supplémentaires comme l'ouverture automatique du clavier logiciel au lancement de l'application.

Veuillez noter qu'il existe un moyen plus simple de faire en sorte que TextInput se concentre automatiquement ( autoFocus={true} prop ), mais pour les besoins de cet exemple, nous ne l'utiliserons pas.

Ajoutez une référence au TextInput avec prop :

ref={ref => this.searchInput = ref}

Et remplacez la méthode de cycle de vie componentDidMount() comme ceci :

 componentDidMount(){ this.searchInput.focus(); }

Rechargez l'application et le clavier s'ouvrira automatiquement pour nous.

Méthodes de cycle de vie des composants

Nous avons déjà créé un composant, mais passons en revue la vie d'un composant.

Voici le flux du cycle de vie de React :

  • constructor() - Le constructeur est toujours appelé au démarrage de l'application
  • static _getDerivedStateFromProps_(props, state) - Appelé avant le rendu et après la mise à jour. Renvoie l'objet pour mettre à jour l'état. Renvoie null pour ne rien mettre à jour.
  • render() - Le rendu est requis pour chaque classe React Component. Il est utilisé pour rendre la vue.
  • componentDidMount() - Est invoqué après le rendu et le montage du composant dans l'arborescence de la vue.
  • shouldComponentUpdate(nextProps, nextState) - Appelé après le changement d'état ou d'accessoires. Le retour par défaut est vrai après chaque mise à jour d'état. Appelle render() si renvoie vrai.
  • getSnapshotBeforeUpdate(prevProps, prevState) - Appelé juste avant que la sortie rendue ne soit validée.
  • componentDidUpdate(prevProps, prevState, snapshot) - Appelé après avoir rendu une nouvelle mise à jour. Il n'est pas appelé après le premier render() .
  • componentWillUnmount() - Appelé juste avant que le composant ne soit démonté et détruit.

Tableau du cycle de vie des composants

Composants réutilisables

Nous avons souvent besoin de créer des composants réutilisables lorsque nous travaillons sur le projet. Il existe deux manières de créer un composant :

  1. Création d'une classe qui étend React.Component . Cette méthode doit être utilisée si nous avons besoin de méthodes de cycle de vie.
  2. En écrivant une fonction qui retourne View pour une syntaxe plus simple.

Puisque nous avons déjà créé des classes Component, créons une fonction pour cette instance.

Supposons que nous ayons besoin d'un analogue à <CardView> . Créez un dossier « commun » sous le répertoire ./src .

Créez CardView.js .

 import React from "react"; import {View} from "react-native"; export default CardView = (props) => { return ( //Style will be merged from default containerStyle //and props.style. props.style attributes will override //values if parameters are same. <View style={{...styles.containerStyle, ...props.style}}> {/* props.children contain subviews add this line if the component is container */} {props.children} </View> ); }; const styles = { containerStyle: { borderRadius: 4, margin: 5, padding: 5, elevation: 5, shadowColor: 'black', shadowRadius: 5, shadowOpacity: 0.5, shadowOffset: {width: 0, height: 3}, backgroundColor: 'white' } };

LoginForm en utilisant notre nouvelle mise en page CardView :

 import React from "react"; import {TextInput, Platform, Button, StyleSheet} from "react-native"; import CardView from "../common/components/CardView"; export default class LoginForm extends React._Component _{ render() { return ( //Override default style <CardView style={{ borderRadius: 4, backgroundColor: '#fff' }}> <TextInput placeholder="Email" style={styles.textInputStyle}/> <TextInput placeholder="Password" style={styles.textInputStyle} secureTextEntry={true}/> <Button color="#841584" title="Login" onPress={() => console.log("onLoginPress")} buttonStyle={styles.buttonStyle}/> </CardView> ); } } const styles = StyleSheet.create({ buttonStyle: { elevation: 5, height: 40 }, textInputStyle: { padding: 10, //Additional params to make //iOS inputs prettier ...Platform.select({ ios: { borderRadius: 2, marginTop: 5, backgroundColor: '#eeeeee' } }) } });

Importez la classe LoginForm dans la classe App et enveloppez-la avec View

 <View style={{flex: 1, justifyContent: 'center'}}> <LoginForm/> </View>

Si vous modifiez les paramètres dans les styles, vous pouvez obtenir quelque chose de beaucoup plus joli.

Application de formulaire de connexion générée finale

La navigation

La navigation vers différentes scènes est un élément essentiel pour la plupart des applications. Nous allons créer une application de navigateur Reddit /r/pics.

Créer une navigation dans React Native est assez simple.

Conditions préalables

  • Installez react-navigation avec yarn ou npm
  • Installer axios avec yarn ou du npm

Commençons par créer deux composants différents.

Remarque : La plupart du code ci-dessous devrait déjà vous être familier. Je vais coller toute la classe.

PictureList.js:

 import React from 'react'; import { ActivityIndicator, FlatList, Image, Text, TouchableHighlight, View } from "react-native"; import axios from "axios"; import CardView from "../common/CardView"; export default class PictureList extends React.Component { state = {loading: true, error: null, posts: null}; componentDidMount() { axios.get('https://www.reddit.com/r/pics.json') .then(response => { this.setState({ posts: response.data.data.children, loading: false }) }).catch(error => { this.setState({ error: error.message, loading: false }) }) } render() { return ( <View style={{flex: 1, justifyContent: 'center'}}> // FlatList ~ ListView // data - DataSource for the List // renderItem - function returns View item // keyExtractor - Unique id for items {this.state.posts && <FlatList data={this.state.posts} renderItem={this.renderItem.bind(this)} keyExtractor={(item) => (item.data.id + '')}/>} {this.state.loading && <ActivityIndicator size="large" color="#f4511e"/>} </View> ); } navigateToPicture(title, url) { this.props.navigation.navigate('PicturePreview', { 'title': title, 'url': url }) } renderItem(item) { //Destructuring values from item //Read more 'ES6 destructuring' const {data} = item.item; const {title} = data; const {url} = data.preview.images[0].source; return ( //Clickable view <TouchableHighlight onPress={() => this.navigateToPicture(title, url)}> {/Reusing our CardView/} <CardView> <Image style={{height: 150}} source={{uri: url}}/> <Text style={{padding: 5}}>{title}</Text> </CardView> </TouchableHighlight> ) } }

PicturePreview.js :

 import React from 'react'; import {Image} from "react-native"; export default class PicturePreview extends React.Component { //Destructure navigation //Set title to header static _navigationOptions = ({navigation}) => ({ title: navigation.state.params.title }); render() { const {url} = this.props.navigation.state.params; return (<Image style={{flex: 1}} source={{uri: url}}/>) } }

Les options de navigationOptions seront automatiquement invoquées par React-Navigation.

Passons maintenant à App.js

Remarque : Il existe de nombreux types de navigation dans React-Navigation. Aujourd'hui, nous allons nous concentrer sur StackNavigation . Veuillez vous référer au site officiel pour des informations détaillées.

 import React from 'react'; import {createStackNavigator} from "react-navigation"; import PictureList from "./components/PictureList"; import PicturePreview from "./components/PicturePreview"; export default class App extends React.Component { render() { return ( <Router/> ); } } //Customize the header_ const NavigationOptions = { headerTintColor: '#fff', headerStyle: { backgroundColor: '#f4511e', } }; //Create the router. const Router = createStackNavigator({ //Name the screen 'PictureList': { //Link the Component screen: PictureList, //Additional navigation options navigationOptions: { title: '/r/pics Browser', ...NavigationOptions } }, 'PicturePreview': { screen: PicturePreview, navigationOptions: NavigationOptions } }, { //Root initialRouterName: 'PictureList' } );

Comme vous pouvez le voir, tout ce que nous avons à faire est de créer un routeur de navigation et de faire en sorte que l' application le rende. Si tout s'est bien passé, nous aurons une application de navigateur Reddit /r/pics fonctionnelle.

Android:

Application de navigation finale sous Android

iOS :

Application de navigation finale dans iOS

React Native est incroyable !

Depuis que j'ai commencé à programmer, j'ai eu des expériences de développement purement mobile. Mais maintenant, je peux coder à peu près n'importe quoi avec React : mobile, ordinateur de bureau et Web.

Si vous décidez de commencer à développer votre prochaine application étonnante en utilisant React Native, vous constaterez qu'elle a ses bizarreries et quelques bogues ici et là, mais React Native est très fonctionnel et idéal pour la plupart des projets.

Connexes : Construire un scanner QR : un didacticiel sur l'appareil photo natif React