Guide de développement d'applications Web natives React

Tu t'es réveillé. Le soleil brille, les oiseaux gazouillent. Dans le monde, personne n'est en guerre contre personne, personne ne meurt de faim et le même code peut être utilisé dans des projets Web et dans des applications natives. Comme ce serait bien! Malheureusement, seul un code universel est visible à l'horizon, mais le chemin vers celui-ci, encore aujourd'hui, est encore plein de surprises.

image

Le matériel, dont nous publions la traduction aujourd'hui, est un guide petit mais assez détaillé pour le développement d'applications universelles utilisant React Native.

Pourquoi tout cela?


L'abréviation "PWA" ( Progressive Web Apps , applications web progressives) est aujourd'hui bien connue de tous, cet acronyme à trois lettres ne semble être qu'une baleine dans une mer de termes techniques. Mais cette technologie populaire n'est pas encore sans défauts . Il y a beaucoup de difficultés technologiques associées à de telles applications, il y a des situations dans lesquelles un développeur est obligé de créer simultanément des applications natives et Web. Voici un bon article comparant PWA et les applications natives.

Peut-être que les entreprises devraient se concentrer uniquement sur les applications natives? Non, ça n'en vaut pas la peine. C'est une grosse erreur. En conséquence, le développement d'une seule application universelle devient une étape logique. Cela vous permet de réduire le temps de développement, de réduire le coût de création et de support des projets. Ce sont ces caractéristiques des applications universelles qui m'ont poussé à une petite expérience.

Il s'agit d'un exemple d'application universel dans le domaine du commerce électronique pour la commande de produits alimentaires. Après l'expérience, j'ai créé un modèle pour de futurs projets et pour de nouvelles recherches.


Papu est une application de commande de nourriture conçue pour Android, iOS et le Web

Blocs de construction d'application


Ici, nous utilisons React, nous devons donc séparer la logique d'application de l'interface utilisateur. Il est préférable d'utiliser une sorte de système pour contrôler l'état d'une application comme Redux ou Mobx. Une telle démarche rend immédiatement la logique du fonctionnement de l'application universelle. Il, sans modifications, peut être utilisé sur différentes plateformes.

La partie visuelle de l'application est une autre conversation. Pour construire l'interface d'application, vous devez disposer d'un ensemble universel de primitives, de blocs de construction de base. Ils doivent fonctionner à la fois sur le Web et dans l'environnement natif. Malheureusement, la langue du Web et la langue des plates-formes natives sont deux choses différentes.

Par exemple, un conteneur Web standard vous contactera comme ceci:

<div> !  -   !</div> 

Et natif - comme ça:

 <View>!  -    React Native</View> 

Certaines personnes intelligentes ont trouvé un moyen de sortir de cette situation. Le résultat était des bibliothèques d'éléments spécialisés. L'une de mes préférées est la merveilleuse bibliothèque Web React Native . Il prend en charge non seulement les primitives de base de l'application, permettant l'utilisation de composants React Native sur le Web (pas tous les composants!), Mais donne également accès à diverses API React Native. Parmi eux, AsyncStorage , Platform , Animated , AsyncStorage et bien d'autres. Jetez un œil aux excellents exemples qui se trouvent dans le manuel de cette bibliothèque.

Motif


Nous avons compris les primitifs. Mais nous devons encore connecter l'environnement pour le développement Web et pour le développement natif. Mon projet utilise create-react-app (pour une application web) et un script d'initialisation React Native (pour une application native, sans Expo). Tout d'abord, j'ai créé un projet avec cette commande: create-react-app rnw_web . Il a ensuite créé un deuxième projet: react-native init raw_native . Ensuite, en suivant l'exemple de Victor Frankenstein, j'ai pris les fichiers package.json de ces deux projets et les ai fusionnés. Après cela, dans le dossier du nouveau projet, j'ai alimenté le nouveau fichier de yarn . Voici le fichier de package en question:

 { "name": "rnw_boilerplate", "version": "0.1.0", "private": true, "dependencies": {   "react": "^16.5.1",   "react-art": "^16.5.1",   "react-dom": "^16.5.1",   "react-native": "0.56.0",   "react-native-web": "^0.9.0",   "react-navigation": "^2.17.0",   "react-router-dom": "^4.3.1",   "react-router-modal": "^1.4.2" }, "devDependencies": {   "babel-jest": "^23.4.0",   "babel-preset-react-native": "^5",   "jest": "^23.4.1",   "react-scripts": "1.1.5",   "react-test-renderer": "^16.3.1" }, "scripts": {   "start": "node node_modules/react-native/local-cli/cli.js start",   "test": "jest",   "start-ios": "react-native run-ios",   "start-web": "react-scripts start",   "build": "react-scripts build",   "test-web": "react-scripts test --env=jsdom",   "eject-web": "react-scripts eject" } } 

Veuillez noter qu'il n'y a aucune fonction de navigation dans cette version du fichier. Ensuite, vous devez copier tous les fichiers de code source des dossiers de l'application Web et de l'application native dans le dossier du nouveau projet unifié.


Dossiers à copier dans un nouveau projet

Maintenant, dans le dossier src , qui se trouve dans le répertoire du nouveau projet, créez deux fichiers: App.js et App.native.js . Grâce à webpack, nous pouvons utiliser des extensions de nom de fichier pour indiquer au bundler où les fichiers à utiliser. La séparation des fichiers d' App est vitale car nous allons utiliser différentes approches pour naviguer dans les applications.

Voici le fichier App.js pour le Web. react-router utilisé pour la navigation.

 // App.js - WEB import React, { Component } from "react"; import { View } from "react-native"; import WebRoutesGenerator from "./NativeWebRouteWrapper/index"; import { ModalContainer } from "react-router-modal"; import HomeScreen from "./HomeScreen"; import TopNav from "./TopNav"; import SecondScreen from "./SecondScreen"; import UserScreen from "./UserScreen"; import DasModalScreen from "./DasModalScreen"; const routeMap = { Home: {   component: HomeScreen,   path: "/",   exact: true }, Second: {   component: SecondScreen,   path: "/second" }, User: {   component: UserScreen,   path: "/user/:name?",   exact: true }, DasModal: {   component: DasModalScreen,   path: "*/dasmodal",   modal: true } }; class App extends Component { render() {   return (     <View>       <TopNav />       {WebRoutesGenerator({ routeMap })}       <ModalContainer />     </View>   ); } } export default App; 

Voici le App.js pour l'application React Native. Ici, react-navigation utilisé react-navigation .

 // App.js - React Native import React, { Component } from "react"; import { createStackNavigator, createBottomTabNavigator } from "react-navigation"; import HomeScreen from "./HomeScreen"; import DasModalScreen from "./DasModalScreen"; import SecondScreen from "./SecondScreen"; import UserScreen from "./UserScreen"; const HomeStack = createStackNavigator({ Home: { screen: HomeScreen, navigationOptions: { title: "Home" } } }); const SecondStack = createStackNavigator({ Second: { screen: SecondScreen, navigationOptions: { title: "Second" } }, User: { screen: UserScreen, navigationOptions: { title: "User" } } }); const TabNav = createBottomTabNavigator({ Home: HomeStack, SecondStack: SecondStack }); const RootStack = createStackNavigator( {   Main: TabNav,   DasModal: DasModalScreen }, {   mode: "modal",   headerMode: "none" } ); class App extends Component { render() {   return <RootStack />; } } export default App; 

C'est ainsi que j'ai créé un modèle d'application simple et préparé la plate-forme pour d'autres travaux. Vous pouvez essayer ce modèle en consultant ce référentiel.

Maintenant, nous allons compliquer un peu ce modèle, ajouter un système de routage / navigation.

Problèmes de navigation et leurs solutions


Une application, à moins qu'elle ne se compose d'un seul écran, a besoin d'une sorte de système de navigation. Maintenant (nous parlons de septembre 2018), il n'y a qu'un seul système de travail universel, adapté à la fois aux applications Web et natives. Il s'agit du React Router . Pour le web, cette solution fonctionne bien, mais dans le cas des projets React Native, tout n'est pas si clair.

Dans React Router Native, il n'y a pas de transition entre les écrans, il n'y a pas de prise en charge du bouton Retour (pour la plate-forme Android), il n'y a pas d'écrans modaux, de barres de navigation et d'autres fonctionnalités. D'autres outils de navigation, tels que React Navigation , ont ces capacités.

J'ai utilisé cette bibliothèque particulière, mais vous pouvez choisir autre chose. Par conséquent, dans mon projet, React Router est responsable de la navigation dans l'application Web et React Navigation pour la navigation dans l'application native. Cependant, cela crée un nouveau problème. Le fait est que les approches de navigation et de transfert de paramètres dans ces systèmes sont très différentes.

Afin de préserver l'esprit de React Native Web, en utilisant partout une approche similaire à celle utilisée dans les applications natives, j'ai approché la solution de ce problème en créant des routes web et en les enveloppant dans HOC. Cela m'a donné l'opportunité de créer une API qui rappelle React Navigation.

Cette approche m'a permis de passer d'un écran à l'autre d'une application Web, éliminant ainsi la nécessité de créer des composants distincts pour deux types d'applications.

La première étape de la mise en œuvre de ce mécanisme consiste à créer un objet avec une description des itinéraires pour l'application Web:

 import WebRoutesGenerator from "./NativeWebRouteWrapper"; //   ,    React Router     HOC const routeMap = { Home: {   screen: HomeScreen,   path: '/',   exact: true }, Menu: {   screen: MenuScreen,   path: '/menu/sectionIndex?' } } //  render <View> {WebRoutesGenerator({ routeMap })} </View> 

En fait, voici une copie de la fonction de création de React Navigation avec l'ajout de capacités spécifiques à React Router.

Ensuite, en utilisant ma fonction d'assistance, je crée react-router routes de react-router et je les enveloppe dans HOC. Cela vous permet de cloner le composant d' screen et d'ajouter une navigation à ses propriétés. Cette approche imite le comportement de React Navigation et met à disposition des méthodes telles que navigate() , goBack() , getParam() .

Écrans modaux


React Navigation, grâce à createStackNavigator , permet à une certaine page de l'application de sortir par le bas sous la forme d'un écran modal. Pour y parvenir dans une application Web, j'ai dû utiliser la bibliothèque modale React Router . Pour travailler avec l'écran modal, vous devez d'abord ajouter l'option appropriée à l'objet routeMap :

 const routeMap = { Modal: {   screen: ModalScreen,   path: '*/modal',   modal: true //    ModalRoute     } } 

De plus, le <ModalContainer /> de la bibliothèque <ModalContainer /> react-router-modal doit être ajouté à la présentation de l'application. La page correspondante y sera affichée.

Navigation entre les écrans


Grâce au HOC de notre développement (temporairement ce composant est appelé NativeWebRouteWrapper , et c'est d'ailleurs un nom terrible), nous pouvons utiliser presque le même ensemble de fonctions que dans React Navigation pour organiser le mouvement entre les pages dans la version web de l'application:

 const { product, navigation } = this.props <Button onPress={navigation.navigate('ProductScreen', {id: product.id})} title={`Go to ${product.name}`} /> <Button onPress={navigation.goBack} title="Go Back" /> 

Revenez à l'écran précédent.


Dans React Navigation, vous pouvez revenir aux n écrans qui se trouvent dans la pile de navigation. Similaire dans React Router n'est pas disponible, il n'y a pas de pile de navigation. Afin de résoudre ce problème, nous devons importer la fonction pop de notre propre conception dans le code. En l'appelant, nous lui donnerons plusieurs paramètres:

 import pop from '/NativeWebRouteWrapper/pop' render() { const { navigation } = this.props return (   <Button     onPress={pop({screen: 'FirstScreen', n: 2, navigation})}     title="Go back two screens"   /> ) } 

Nous décrivons ces paramètres:

  • screen - le nom de l'écran (utilisé par React Router dans la version Web de l'application).
  • n est le nombre d'écrans à retourner en utilisant la pile (en utilisant React Navigation).
  • navigation - un objet qui fournit la navigation.

Résultats du travail


Si vous voulez expérimenter l'idée de développer des applications universelles présentées ici, j'ai créé deux modèles.

Le premier est un environnement propre et universel pour le développement d'applications Web et d'applications natives.

Le second est, en substance, le premier modèle, qui a été étendu en raison de mon système d'organisation de la navigation dans l'application.

Voici une application de démonstration papu basée sur les considérations ci-dessus. Il est plein d'erreurs et d'impasses, mais vous pouvez l'assembler vous-même, l'exécuter dans un navigateur et sur un appareil mobile, et en pratique avoir une idée de la façon dont tout cela fonctionne.

Résumé


La communauté des développeurs React a bien sûr besoin d'une bibliothèque universelle pour organiser la navigation des applications, car cela simplifiera le développement de projets comme celui dont nous avons parlé. Ce serait très bien si la bibliothèque React Navigation fonctionnait sur le web (en fait, cette fonctionnalité est déjà disponible , mais travailler avec elle n'est pas sans difficultés).

Chers lecteurs! Profitez-vous de React pour créer des applications universelles?

Source: https://habr.com/ru/post/fr428568/


All Articles