Expo est un ensemble d'outils facilitant le codage des applications natives de React. Dans ce tutoriel, je vais vous montrer comment créer rapidement des applications natives React avec Expo..
Avec Expo, les développeurs peuvent créer des applications natives React sans toutes les frustrations liées à l'installation et à la configuration de dépendances logicielles telles qu'Android Studio, Xcode ou tous les autres outils nécessaires pour développer et exécuter une application React Native..
Dans ce tutoriel, je vais vous montrer comment créer un jeu de mémoire simple avec Expo. En chemin, vous apprendrez également ce qui suit:
Expo est un cadre permettant de développer rapidement des applications natives React. C'est comme Laravel ou Symphony pour les développeurs PHP, ou Ruby on Rails pour les développeurs Ruby. Expo fournit une couche au-dessus des API natives de React pour faciliter leur utilisation et leur gestion. Il fournit également des outils qui facilitent l’amorçage et le test des applications natives de React. Enfin, il fournit des composants d'interface utilisateur et des services qui ne sont généralement disponibles que lorsque vous installez un composant tiers React Native. Tous sont disponibles via le SDK Expo..
Avant de poursuivre, il est important de connaître certaines des limites d’Expo:
Même avec ces limitations, il est important de garder à l'esprit qu'Expo est un cadre entièrement fonctionnel prenant largement en charge les API Android ou iOS couramment utilisées. Cela signifie que la plupart des fonctionnalités dont les applications ont généralement besoin sont couvertes. Donc, il n'est souvent pas nécessaire de regarder en dehors de l'Expo pour implémenter la fonctionnalité native.
L'application que nous allons créer est un jeu de mémoire. Vous êtes peut-être familiarisé avec ce type de jeu. L'utilisateur doit trouver les paires correspondantes en retournant les cartes deux à la fois. Voici à quoi ressemble l'écran par défaut:
Et voici à quoi cela ressemble une fois que toutes les paires ont été ouvertes:
Une fois le jeu résolu, l’utilisateur peut appuyer sur le bouton réinitialiser bouton pour réinitialiser les éléments à leur état initial. Cela leur permet de tout recommencer..
Contrairement à Plain React Native, dans lequel vous devez installer et configurer Android Studio ou Xcode et d'autres dépendances, avec Expo, il ne reste que quelques étapes à suivre pour commencer à développer des applications:
npm install exp --global
Une fois que vous avez installé toutes les dépendances, vous pouvez maintenant générer une nouvelle application Expo:
exp init MemoryGame
Une fois que cela est fait, il va créer un nouveau dossier appelé Jeux de mémoire. Naviguez à l'intérieur et commencez à exécuter le serveur de développement:
cd MemoryGame exp start
Alternativement, vous pouvez également utiliser Expo XDE. Cela vous permet de créer et d'exécuter des applications Expo via une interface graphique. Vous pouvez télécharger le programme d'installation à partir du dépôt Expo GitHub. Actuellement, il ne supporte que Windows et Mac. Donc, si vous êtes sur Ubuntu ou Linux, il est préférable de s'en tenir à la ligne de commande pour l'instant..
Une fois que le serveur de développement est en cours d'exécution, vous devriez maintenant pouvoir voir quelque chose comme ceci:
C'est le code QR qui pointe sur l'aperçu en direct du projet. Ouvrez l'application client Expo sur votre téléphone et scannez le code à l'aide du scanner QR. À ce stade, vous devriez maintenant pouvoir afficher l'écran par défaut. Chaque fois que vous frappez Les contrôles sur l’un des fichiers du projet, l’aperçu doit se recharger automatiquement pour refléter les modifications.
Vous pouvez trouver le code source complet du projet sur son dépôt GitHub. Ou si vous voulez essayer l'application, vous pouvez consulter la démo. Il suffit de sélectionner le code QR et de le scanner sur votre téléphone à l'aide de l'application client Expo.
Nous sommes maintenant prêts à coder l'application. Commençons par quelques composants de l'interface utilisateur avant de revenir en arrière et de mettre en œuvre le composant principal.
L'en-tête est utilisé pour afficher le titre de l'application. Créer un Composants dossier. À l'intérieur, créez un Header.js déposer et ajouter ce qui suit:
importer Réagir de 'réagir'; importer StyleSheet, Text, View de 'react-native'; exporter la classe par défaut Header etend React.Component render () return () const styles = StyleSheet.create (en-tête: flex: 1, flexDirection: 'colonne', alignSelf: 'stretch', paddingTop: 20, paddingBottom: 5, backgroundColor: '# f3f3f3', header_text: fontWeight: 'bold', fontSize: 17, textAlign: 'center'); Jeux de mémoire
Ceci est juste un composant de base de React Native, avec un style pour correspondre à l'interface utilisateur de notre application.
Ensuite vient le composant permettant d’afficher le score (composants / Score.js):
importer Réagir de 'réagir'; importer StyleSheet, Text, View de 'react-native'; exporter la classe par défaut Score étend React.Component render () return () const styles = StyleSheet.create (score_container: flex: 1, alignItems: 'center', remplissage: 10, score: fontSize: 40, fontWeight: 'bold'); this.props.score
Encore une fois, juste un composant d'affichage simple avec une vue texte et un style de base.
Le composant de carte (composants / Card.js) affichera les cartes. Ces cartes utilisent des icônes du jeu d’icônes vectorielles Expo. C'est l'une des fonctionnalités qui sortent de la boîte lorsque vous utilisez Expo: elle inclut des icônes de jeux d'icônes tels que FontAwesome, Entypo et Ionicons..
Dans le code ci-dessous, vous pouvez voir que nous utilisons uniquement FontAwesome. Il a l'icône que nous voulons pour afficher l'état par défaut de la carte: un point d'interrogation. Comme vous le verrez plus loin dans le composant principal de l'application, nous utiliserons également des icônes de Entypo et Ionicons. La référence à ces sources d'icônes sera transmise à ce composant. Il n'est donc pas nécessaire de les spécifier ici:
importer Réagir de 'réagir'; importer StyleSheet, Text, View, TouchableHighlight à partir de 'react-native'; importer FontAwesome depuis '@ expo / vector-icons'; // utilise FontAwesome à partir des icônes vectorielles expo
À l'intérieur de rendre()
En utilisant cette méthode, nous n’utilisons la source et l’icône comme accessoires que si la carte est ouverte. Par défaut, l'icône du point d'interrogation de FontAwesome sera uniquement affichée. Mais si la carte est ouverte, elle utilisera la source de l'icône, l'icône et la couleur qui ont été transmises comme accessoires..
Chacune des cartes peut être exploitée. Quand on tape, le clickCard ()
la fonction sera exécutée, qui est également transmise via les accessoires. Plus tard, vous verrez ce que la fonction fait, mais pour l'instant, sachez simplement qu'elle met à jour l'état pour révéler l'icône sur la carte:
classe d'exportation par défaut de la carte s'étend React.Component render () let CardSource = FontAwesome; // définir FontAwesome comme source d'icônes par défaut let icon_name = 'question-circle'; let icon_color = '# 393939'; if (this.props.is_open) CardSource = this.props.src; icon_name = this.props.name; icon_color = this.props.color; revenir ()
N'oubliez pas d'ajouter les styles:
const styles = StyleSheet.create (card: flex: 1, alignItems: 'center', card_text: fontSize: 50, fontWeight: 'bold');
Nous utiliserons également une fonction d'assistance appelée mélanger ()
. Cela nous permet de trier le tableau de cartes dans un ordre aléatoire afin que leur ordre soit différent chaque fois que le jeu est réinitialisé:
Array.prototype.shuffle = function () var i = this.length, j, temp; if (i == 0) renvoie ceci; tandis que (- i) j = Math.floor (Math.random () * (i + 1)); temp = this [i]; ceci [i] = ceci [j]; ceci [j] = temp; retourne ceci;
Le composant principal (App.js) contient la logique principale de l'application et rassemble tout. Commencez par inclure les packages React et Expo que nous utiliserons. Cette fois, nous utilisons toutes les sources d'icônes d'icônes vectorielles Expo:
importer Réagir de 'réagir'; importer StyleSheet, View, Button de 'react-native'; importer Ionicons, FontAwesome, Entypo depuis '@ expo / vector-icons';
Ensuite, incluez les composants et l’assistant que nous avons créés précédemment:
importer l'en-tête de './components/Header'; importer Score de './components/Score'; importer une carte de './components/Card'; importer des aides de './helpers';
À l'intérieur du constructeur, nous créons d'abord le tableau qui représente les cartes uniques. src
est la source de l'icône, prénom
est le nom de l'icône (vous pouvez trouver les noms sur GitHub si vous voulez utiliser d'autres icônes), et Couleur
est naturellement la couleur de l'icône:
classe d'exportation par défaut App étend React.Component constructeur (props) super (props); // lie les fonctions à la classe this.renderCards = this.renderCards.bind (this); this.resetCards = this.resetCards.bind (this); // icône sources let sources = 'fontawesome': FontAwesome, 'entypo': Entypo, 'ionicons': Ionicons; // les icônes uniques à utiliser permettent aux cartes = [src: 'fontawesome', nom: 'coeur', couleur: 'rouge', src: 'entypo', nom: 'plume', couleur: '# 7d4b12 ', src:' entypo ', nom:' lampe de poche ', couleur:' # f7911f ', src:' entypo ', nom:' fleur ', couleur:' # 37b24d ', src:' entypo ', nom:' lune ', couleur:' # ffd43b ', src:' entypo ', nom:' youtube ', couleur:' # FF0000 ', src:' entypo ', nom:' boutique ', color: '# 5f5f5f', src: 'fontawesome', nom: 'github', couleur: '# 24292e', src: 'fontawesome', nom: 'skype', couleur: '# 1686D9', src: 'fontawesome', nom: 'send', couleur: '# 1c7cd6', src: 'ionicons', nom: 'ios-magnet', couleur: '# d61c1c', src: 'ionicons' , nom: 'logo-facebook', couleur: '# 3C5B9B']; // next: ajoute du code créant le clone et définissant les cartes dans l'état
Notez qu'au lieu de spécifier directement le src
comme FontAwesome
, Entypo
ou Ioniques
pour chacun des objets, nous utilisons les noms de propriété utilisés dans le sources
objet. En effet, nous devrons créer une copie du tableau de cartes pour que chaque carte ait une paire. Créer une copie en utilisant des méthodes de tableau telles que tranche()
créera une copie du tableau, mais le problème est qu’une fois les objets individuels modifiés dans la copie ou l’original, les deux tableaux sont également modifiés..
Ceci nous amène à la solution ci-dessous qui consiste à créer un objet complètement nouveau en convertissant le cartes
tableau dans une chaîne, puis l’analyser pour le reconvertir en tableau. C'est la raison pour laquelle nous utilisons des chaînes car les fonctions ne peuvent pas être converties en chaînes. Nous combinons ensuite les deux pour créer le tableau, qui contient toutes les cartes dont nous avons besoin:
let clone = JSON.parse (JSON.stringify (cartes)); // crée un tableau complètement nouveau à partir du tableau de cartes this.cards = cards.concat (clone); // combine l'original et le clone
Ensuite, parcourez ce tableau et générez un ID unique pour chacun, définissez la source de l'icône, puis définissez-le par défaut sur un état fermé:
// ajoute l'ID, la source et définit l'état par défaut pour chaque carte this.cards.map ((obj) => let id = Math.random (). toString (36) .substring (7); obj.id = id ; obj.src = sources [obj.src]; obj.is_open = false;);
Triez les cartes au hasard et définissez l'état par défaut:
this.cards = this.cards.shuffle (); // trie les cartes de manière aléatoire // définit l'état par défaut this.state = current_selection: [], // ce tableau contiendra un tableau d'objets de carte actuellement sélectionnés par l'utilisateur. Cela ne contiendra que deux objets à la fois. selected_pairs: [], // les noms des icônes. Ce tableau est utilisé pour les exclure des scores de sélection suivants: 0, // cartes de score utilisateur par défaut: this.cards // les cartes mélangées
le rendre()
méthode affiche l’en-tête, les cartes, le score et le bouton permettant de réinitialiser la partie en cours. Il utilise le renderRows ()
fonction pour rendre les lignes individuelles de la carte. L'écran aura six lignes contenant quatre cartes chacune:
render () return () this.renderRows.call (this)
Voici le code pour le renderRows ()
une fonction. Cela utilise le getRowContents ()
fonction, qui est responsable de la création d’un tableau de tableaux contenant quatre éléments. Cela nous permet de restituer chaque ligne, puis d’utiliser une autre fonction pour restituer les cartes à chaque itération du fichier. carte()
une fonction:
renderRows () let contents = this.getRowContents (this.state.cards); return contents.map ((cards, index) => return (this.renderCards (cartes) ) );
Ici se trouve le getRowContents ()
une fonction:
getRowContents (cartes) let content_r = []; laisser contenu = []; laisser compter = 0; cards.forEach ((item) => compte + = 1; contents.push (objet); if (compte == 4) contenus_r.push (contenu) compte = 0; contenus = [];); return contents_r;
Suivant est le renderCards ()
une fonction. Ceci accepte le tableau des objets de la carte et les rend via le Carte
composant. Tout ce que nous avons à faire ici est de passer les propriétés individuelles de chaque objet de carte en tant qu’accessoires. Ceci est ensuite utilisé pour restituer la bonne icône, comme vous l'avez vu dans le code du Carte
composant. le clickCard ()
La fonction est également transmise comme accessoire. L'ID de la carte est transmis à cette fonction afin que la carte unique puisse être identifiée et mise à jour:
renderCards (cartes) return cards.map ((card, index) => return () );
À l'intérieur de clickCard ()
fonction, nous obtenons les détails de la carte sélectionnée et vérifions si elle doit être traitée ultérieurement:
clickCard (id) let selected_pairs = this.state.selected_pairs; let current_selection = this.state.current_selection; laisser score = this.state.score; // récupère l'index de la carte actuellement sélectionnée let index = this.state.cards.findIndex ((card) => return card.id == id;); let cards = this.state.cards; // la carte ne devrait pas déjà être ouverte et ne figure pas dans le tableau de cartes dont les paires sont déjà sélectionnées si (cartes [index] .is_open == false && selected_pairs.indexOf (cartes [index]. nom) == - 1) // suivant: ajouter un code pour traiter la carte sélectionnée
Maintenant remplissons le code pour manipuler une carte sélectionnée.
Tout d'abord, nous ouvrons la carte et l'ajoutons au tableau des cartes actuellement sélectionnées:
cartes [index] .is_open = true; current_selection.push (index: index, nom: cartes [index] .name); // next: ajoute un code pour déterminer si l'utilisateur a sélectionné la bonne paire ou non
Une fois que le tableau des cartes sélectionnées contient deux éléments, nous vérifions si les noms des icônes sont identiques. Si c'est le cas, cela signifie que l'utilisateur a sélectionné la bonne paire. S'ils ne sont pas identiques, la paire est incorrecte. Dans ce cas, nous fermons la première carte sélectionnée et ajoutons un peu de retard avant de fermer la deuxième carte. (Ainsi, l'utilisateur peut voir l'icône de la carte avant qu'elle ne revienne à l'état fermé.)
if (current_selection.length == 2) if (current_selection [0] .name == current_selection [1] .name) score + = 1; // incrémente la partition selected_pairs.push (cards [index] .name); else cartes [sélection_actuelle [0] .index] .is_open = false; // ferme le premier // retarde la fermeture de la carte sélectionnée d'une demi-seconde. setTimeout (() => cartes [index] .is_open = false; this.setState (cartes: cartes);, 500); current_selection = []; // next: ajout du code pour la mise à jour de l'état
La dernière chose que nous devons faire dans le gestionnaire d'événements click est de mettre à jour l'état pour refléter les modifications dans l'interface utilisateur:
this.setState (score: score, cartes: cartes, current_selection: current_selection);
Une fonction associée est le gestionnaire d'événements reset. Quand le réinitialiser bouton est activé, nous restaurons simplement l’état par défaut en fermant toutes les cartes et en mélangeant.
resetCards () // ferme toutes les cartes, laissez cartes = this.cards.map ((obj) => obj.is_open = false; return obj;); cartes = cartes.shuffle (); // remanie les cartes // met à jour l'état par défaut this.setState (current_selection: [], selected_pairs: [], cards: cards, score: 0);
Enfin, nous ajouterons quelques styles de base pour donner à notre application une belle apparence..
const styles = StyleSheet.create (conteneur: flex: 1, alignSelf: 'stretch', backgroundColor: '#fff', ligne: flex: 1, flexDirection: 'ligne', corps: flex: 18, justifierContenu: 'espace-entre', remplissage: 10, marginTop: 20);
Depuis que votre serveur de développement Expo a fonctionné pendant tout ce temps, chaque modification doit être transmise à votre appareil mobile avec un rechargement en direct. Essayez l'application et assurez-vous qu'elle fonctionne comme prévu..
C'est tout! Dans ce didacticiel, vous avez appris à utiliser Expo XDE pour connecter rapidement une application React Native. Expo est un très bon moyen de commencer à développer des applications React Native, car il n’est plus nécessaire d’installer beaucoup de logiciels, ce qui est souvent une source de frustration, en particulier pour les débutants. Il fournit également des outils qui facilitent la prévisualisation de l'application en cours de développement. Assurez-vous de consulter les ressources mentionnées sur le site Web de l'Expo si vous souhaitez en savoir plus..
Et en attendant, jetez un coup d'œil à certains de nos autres articles sur le développement d'applications React Native!