Più facile Reagire sviluppo nativo con Expo

Expo è una raccolta di strumenti che semplificano la codifica delle app React Native. In questo tutorial, ti mostrerò come creare rapidamente app React Native usando Expo.

Con Expo, gli sviluppatori possono creare app React Native senza tutte le frustrazioni derivanti dall'installazione e configurazione di dipendenze software come Android Studio, Xcode o tutti gli altri strumenti necessari per sviluppare ed eseguire un'applicazione React Native. 

In questo tutorial, ti mostrerò come creare un semplice gioco di memoria usando Expo. Lungo la strada imparerai anche quanto segue:

  • Come utilizzare gli strumenti forniti da Expo. Ciò include CLI, SDK e l'app client di Expo.
  • Come creare un'applicazione React Native usando Expo.

Cos'è Expo?

Expo è un framework per lo sviluppo rapido di app React Native. È come Laravel o Symphony per gli sviluppatori PHP o Ruby on Rails per gli sviluppatori di Ruby. Expo fornisce un livello in cima alle API React Native per renderle più facili da usare e gestire. Fornisce inoltre strumenti che semplificano il bootstrap e il test delle app React Native. Infine, fornisce componenti e servizi dell'interfaccia utente che sono comunemente disponibili solo quando si installa un componente React Native di terze parti. Tutti questi sono resi disponibili tramite l'SDK di Expo.

Limiti di Expo

Prima di procedere ulteriormente, è importante essere consapevoli di alcuni dei limiti di Expo: 

  1. App di Expo non supporta l'esecuzione del codice di background. Ciò significa che non è possibile, ad esempio, eseguire il codice che ascolta le modifiche alla posizione quando l'app viene chiusa.
  2. Le app di Expos sono limitate alle API native supportate da Expo SDK. Ciò significa che se la tua app ha un caso d'uso molto specifico come la comunicazione con una periferica Bluetooth, l'unica opzione per implementare tale funzionalità è con React Native, o scrivendo codice nativo usando una libreria chiamata ExpoKit.
  3. Expo ti blocca in il loro set di strumenti. Ciò significa che non puoi semplicemente installare e utilizzare la maggior parte degli strumenti eccezionali disponibili per lo sviluppo di React Native, come strumenti da riga di comando, scaffolder e framework UI. Ma la cosa buona è che l'SDK di Expo è compatibile con le semplici app React Native, quindi non avrai alcun problema quando espellerai la tua app da Expo.
  4. I binari standalone delle app di Expo possono essere creati solo online. Expo fornisce uno strumento da riga di comando chiamato Exp. Ciò consente agli sviluppatori di avviare il processo di compilazione sui server di Expo. Una volta completato, verrà fornito un URL per scaricare il file .apk o .ipa file. 

Anche con queste limitazioni, è importante tenere presente che Expo è una struttura completamente funzionale con un sacco di supporto per le API Android o iOS comunemente utilizzate. Ciò significa che ti ha coperto per la maggior parte delle funzionalità di cui le app di solito hanno bisogno. Quindi non c'è spesso bisogno di guardare fuori da Expo per implementare la funzionalità nativa.

Panoramica dell'app

L'app che stiamo per creare è un gioco di memoria. Potresti avere familiarità con questo tipo di gioco: l'utente deve trovare coppie corrispondenti girando le carte due alla volta. Ecco come appare la schermata predefinita:

Ed ecco come sembra che una volta aperte tutte le coppie:

Una volta risolto il gioco, l'utente può toccare reset pulsante per ripristinare gli elementi al loro stato iniziale. Questo permette loro di ricominciare tutto da capo.

Installazione di Expo

A differenza del semplice React Native in cui devi installare e configurare Android Studio o Xcode e altre dipendenze, con Expo ci sono solo pochi passi da seguire per iniziare a sviluppare app:

  1. Scaricare e Installa Node.js. Expo dipende dalla piattaforma Node.js per i suoi strumenti da riga di comando e la gestione delle dipendenze.
  2. Installa il client Expo sul tuo iOS o androide dispositivo. Questo è usato per visualizzare l'anteprima dell'app mentre la stai sviluppando.
  3. Installa lo strumento da riga di comando. Ciò consente di generare un nuovo progetto Expo, avviare un processo di costruzione e altro ancora. Esegui il seguente comando per installarlo: 
npm install exp - global

Generazione di una nuova app Expo

Una volta installate tutte le dipendenze, ora puoi generare una nuova app Expo:

exp init MemoryGame

Una volta fatto, creerà una nuova cartella chiamata Gioco di memoria. Navigare all'interno e avviare l'esecuzione del server di sviluppo:

cd MemoryGame exp start

In alternativa, puoi anche usare Expo XDE. Ciò consente di creare ed eseguire app Expo tramite una GUI. Puoi scaricare l'installer dal repository Expo GitHub. Attualmente supporta solo Windows e Mac. Quindi se sei su Ubuntu o Linux è meglio restare con la linea di comando per ora.

Una volta che il server di sviluppo è in esecuzione, dovresti essere in grado di vedere qualcosa di simile a questo:

Questo è il codice QR che punta all'anteprima dal vivo del progetto. Apri l'app client di Expo sul tuo telefono e scansiona il codice usando lo scanner QR. A questo punto, dovresti essere in grado di visualizzare la schermata predefinita. Ogni volta che colpisci Control-S su uno qualsiasi dei file di progetto, l'anteprima dovrebbe ricaricarsi automaticamente per riflettere le modifiche.

Puoi trovare il codice sorgente completo del progetto sul suo repository GitHub. Oppure, se vuoi provare l'app, puoi dare un'occhiata alla demo. Basta selezionare il codice QR e scansionarlo sul telefono utilizzando l'app client di Expo.

Codifica l'app

Ora siamo pronti per codificare l'app. Iniziamo con alcuni componenti dell'interfaccia utente prima di tornare indietro e implementare il componente principale.

Componente dell'intestazione

L'intestazione viene utilizzata per visualizzare il titolo dell'app. Creare un componenti cartella. Al suo interno, crea un Header.js file e aggiungere il seguente:

import Reagire da "reagire"; import StyleSheet, Text, View da 'react-native'; export default class Header estende React.Component render () return (  Gioco di memoria  );  const styles = StyleSheet.create (header: flex: 1, flexDirection: 'column', alignSelf: 'stretch', paddingTop: 20, paddingBottom: 5, backgroundColor: '#f3f3f3', header_text: fontWeight: 'bold', fontSize: 17, textAlign: 'center');

Questo è solo un componente React Native di base, con uno stile che si abbina all'interfaccia utente della nostra app. 

Punteggio del componente

Il prossimo è il componente per la visualizzazione del punteggio (componenti / Score.js):

import Reagire da "reagire"; import StyleSheet, Text, View da 'react-native'; Esporta la classe di default Punteggio estende React.Component render () return (   This.props.score  );  const styles = StyleSheet.create (score_container: flex: 1, alignItems: 'center', padding: 10, score: fontSize: 40, fontWeight: 'bold');

Ancora una volta, solo un semplice componente di visualizzazione con una visualizzazione di testo e alcuni stili di base.

Componente della carta

Il componente della carta (componenti / Card.js) mostrerà le carte. Queste carte usano icone del set di icone vettoriali di Expo. Questa è una delle caratteristiche che escono subito dalla scatola quando usi Expo: include icone di set di icone come FontAwesome, Entypo e Ionicons. 

Nel codice qui sotto, puoi vedere che stiamo usando FontAwesome. Ha l'icona che vogliamo per visualizzare lo stato di default della carta: un punto interrogativo. Come vedremo più avanti nel componente principale dell'app, useremo anche le icone di Entypo e Ionicons. Il riferimento a tali sorgenti di icone verrà passato a questo componente, quindi non è necessario specificarli qui:

import Reagire da "reagire"; import StyleSheet, Text, View, TouchableHighlight da 'react-native'; importare FontAwesome da "@ expo / vector-icons"; // usa FontAwesome dalle icone vettoriali expo

Dentro il render () metodo, usiamo solo la fonte e l'icona passata come oggetti di scena se la carta è aperta. Per impostazione predefinita, verrà visualizzata l'icona del punto interrogativo solo da FontAwesome. Ma se la carta è aperta, utilizzerà la fonte dell'icona, l'icona e il colore che sono stati passati come oggetti di scena. 

È possibile toccare ciascuna delle carte. Quando toccato, il clickCard () verrà eseguita la funzione, che viene anche passata attraverso i puntelli. Più avanti vedrai cosa fa la funzione, ma per ora, sappi solo che aggiorna lo stato per rivelare l'icona sulla carta: 

export default class Card estende React.Component render () let CardSource = FontAwesome; // imposta FontAwesome come l'icona predefinita source 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;  ritorno (      ); 

Non dimenticare di aggiungere gli stili:

const styles = StyleSheet.create (card: flex: 1, alignItems: 'center', card_text: fontSize: 50, fontWeight: 'bold');

Helpers

Useremo anche una funzione di aiuto chiamata Shuffle (). Questo ci permette di ordinare la matrice di carte in ordine casuale in modo che il loro ordine sia diverso ogni volta che il gioco viene ripristinato:

Array.prototype.shuffle = function () var i = this.length, j, temp; se (i == 0) restituisce questo; while (- i) j = Math.floor (Math.random () * (i + 1)); temp = this [i]; questo [i] = questo [j]; questo [j] = temp;  restituisci questo; 

Componente principale

Il componente principale (App.js) contiene la logica dell'app principale e riunisce tutto. Inizia includendo i pacchetti React ed Expo che utilizzeremo. Questa volta utilizzeremo tutte le risorse delle icone dalle icone vettoriali di Expo:

import Reagire da "reagire"; import StyleSheet, View, Button da 'react-native'; importare Ionicons, FontAwesome, Entypo da "@ expo / vector-icons";

Successivamente, includi i componenti e l'helper che abbiamo creato in precedenza:

importare l'intestazione da "./components/Header"; punteggio di importazione da './components/Score'; scheda di importazione da './components/Card'; importare helper da './helpers';

All'interno del costruttore, per prima cosa creiamo l'array che rappresenta le carte uniche. src è la fonte dell'icona, nome è il nome dell'icona (puoi trovare i nomi su GitHub se vuoi usare altre icone), e colore è, naturalmente, il colore dell'icona:

esportazione di classe predefinita App estende React.Component costruttore (oggetti di scena) super (oggetti di scena); // associa le funzioni alla classe this.renderCards = this.renderCards.bind (this); this.resetCards = this.resetCards.bind (this); // icon sources consente a sources = 'fontawesome': FontAwesome, 'entypo': Entypo, 'ionicons': Ionicons; // le icone uniche da usare let cards = [src: 'fontawesome', nome: 'heart', colore: 'red', src: 'entypo', nome: 'feather', color: '# 7d4b12 ', src:' entypo ', nome:' flashlight ', colore:' # f7911f ', src:' entypo ', nome:' flower ', colore:' # 37b24d ', src:' entypo ', nome:' moon ', colore:' # ffd43b ', src:' entypo ', nome:' youtube ', colore:' # FF0000 ', src:' entypo ', nome:' shop ', color: '# 5f5f5f', src: 'fontawesome', nome: 'github', colore: '# 24292e', src: 'fontawesome', nome: 'skype', colore: '# 1686D9', src: 'fontawesome', nome: 'send', colore: '# 1c7cd6', src: 'ionicons', nome: 'ios-magnete', colore: '# d61c1c', src: 'ionicons' , nome: 'logo-facebook', colore: '# 3C5B9B']; // next: aggiungi il codice creando il clone e impostando le carte nello stato

Si noti che invece di specificare direttamente il src come FontAwesome, Entypo o Ionicons per ciascuno degli oggetti, stiamo usando i nomi delle proprietà usati nel fonti oggetto. Questo perché avremo bisogno di creare una copia della serie di carte in modo che ogni carta abbia una coppia. Creare una copia usando metodi array come fetta() creerà una copia dell'array, ma il problema è che una volta modificati i singoli oggetti sia nella copia che nell'originale, entrambi gli array vengono modificati. 

Questo ci porta alla soluzione qui sotto che è creare un oggetto completamente nuovo convertendo il carte array in una stringa e quindi analizzarlo per convertirlo in un array. Questo è il motivo per cui utilizziamo le stringhe poiché le funzioni non possono essere convertite in stringhe. Combiniamo quindi i due per creare l'array, che contiene tutte le carte di cui abbiamo bisogno:

let clone = JSON.parse (JSON.stringify (cards)); // crea una matrice completamente nuova dalla matrice di carte this.cards = cards.concat (clone); // combina l'originale e il clone

Quindi, passa attraverso quell'array e genera un ID univoco per ognuno, imposta l'origine dell'icona e quindi imposta lo stato chiuso per impostazione predefinita:

// aggiungi l'ID, l'origine e lo stato di default di ogni scheda this.cards.map ((obj) => let id = Math.random (). toString (36) .substring (7); obj.id = id ; obj.src = sources [obj.src]; obj.is_open = false;);

Ordina le carte a caso e imposta lo stato di default:

this.cards = this.cards.shuffle (); // ordina le carte a caso // imposta lo stato predefinito this.state = current_selection: [], // questa matrice conterrà una matrice di oggetti di carta che sono attualmente selezionati dall'utente. Questo conterrà solo due oggetti alla volta. selected_pairs: [], // i nomi delle icone. Questo array viene usato per escluderli da ulteriori punteggi di selezione: 0, // carte punteggio utente predefinite: this.cards // le carte mescolate

Il render () metodo restituisce l'intestazione, le carte, il punteggio e il pulsante per reimpostare il gioco corrente. Sta usando il renderRows () funzione per rendere le singole righe di carte. Lo schermo avrà sei righe contenenti quattro carte ciascuna:

render () return (  
this.renderRows.call (this)

Ecco il codice per il renderRows () funzione. Questo usa il getRowContents () funzione, che è responsabile della creazione di una matrice di matrici con quattro voci ciascuna. Questo ci permette di rendere ogni riga, e quindi usare un'altra funzione per rendere le carte per ogni iterazione del carta geografica() funzione:

renderRows () let contents = this.getRowContents (this.state.cards); return contents.map ((cards, index) => return (  this.renderCards (cards)  ); ); 

Ecco il getRowContents () funzione:

getRowContents (cards) let contents_r = []; let contents = []; let count = 0; cards.forEach ((item) => count + = 1; contents.push (item); if (count == 4) contents_r.push (contents) count = 0; contents = [];); return contents_r; 

Il prossimo è il renderCards () funzione. Questo accetta la matrice di oggetti di carte e li rende tramite il Carta componente. Tutto ciò che dobbiamo fare qui è passare le singole proprietà di ogni oggetto di carta come oggetti di scena. Questo viene quindi utilizzato per rendere l'icona corretta, come hai visto nel codice per il Carta componente. Il clickCard () la funzione è anche passata come sostegno. L'ID della carta viene passato a quella funzione in modo che la carta unica possa essere identificata e aggiornata:

renderCards (cards) return cards.map ((card, index) => return (  ); ); 

Dentro il clickCard () funzione, otteniamo i dettagli della carta selezionata e controlliamo se deve essere elaborata ulteriormente:

clickCard (id) let selected_pairs = this.state.selected_pairs; let current_selection = this.state.current_selection; let score = this.state.score; // ottiene l'indice della scheda attualmente selezionata let index = this.state.cards.findIndex ((card) => return card.id == id;); let cards = this.state.cards; // la carta non dovrebbe essere già aperta e non si trova sull'array di carte le cui coppie sono già selezionate se (cards [indice] .is_open == false && selected_pairs.indexOf (cards [index] .name) === - 1) // next: aggiungi codice per l'elaborazione della carta selezionata

Ora inseriamo il codice per la gestione di una carta selezionata. 

Per prima cosa, apriamo la carta e la aggiungiamo alla matrice delle carte attualmente selezionate:

cards [indice] .is_open = true; current_selection.push (index: index, name: cards [index] .name); // next: aggiungi il codice per determinare se l'utente ha selezionato o meno la coppia corretta

Una volta che ci sono due elementi nella matrice delle carte attualmente selezionate, controlliamo se i nomi delle icone sono gli stessi. Se lo sono, significa che l'utente ha selezionato la coppia corretta. Se non sono uguali, allora è una coppia sbagliata. In tal caso, chiudiamo la prima carta selezionata e aggiungiamo un po 'di ritardo prima di chiudere la seconda carta. (In questo modo l'utente può vedere l'icona della scheda prima che ritorni allo stato chiuso.)

if (current_selection.length == 2) if (current_selection [0] .name == current_selection [1] .name) score + = 1; // incrementa il punteggio selected_pairs.push (cards [index] .name);  else cards [current_selection [0] .index] .is_open = false; // chiudi il primo // ritardo che chiude la carta attualmente selezionata di mezzo secondo. setTimeout (() => cards [indice] .is_open = false; this.setState (cards: cards);, 500);  current_selection = [];  // next: aggiungi il codice per l'aggiornamento dello stato

L'ultima cosa che dobbiamo fare nel gestore di eventi click è aggiornare lo stato per riflettere le modifiche nell'interfaccia utente:

this.setState (score: score, cards: cards, current_selection: current_selection);

Una funzione correlata è il gestore di eventi di reset. Quando il reset toccato, ripristiniamo semplicemente lo stato di default chiudendo tutte le carte e mescolando.

resetCards () // chiudi tutte le carte let cards = this.cards.map ((obj) => obj.is_open = false; return obj;); cards = cards.shuffle (); // re-shuffle le carte // aggiorna allo stato predefinito this.setState (current_selection: [], selected_pairs: [], cards: cards, score: 0); 

Infine, aggiungeremo alcuni stili di base per rendere la nostra app un bell'aspetto.

const styles = StyleSheet.create (container: flex: 1, alignSelf: 'stretch', backgroundColor: '#fff', row: flex: 1, flexDirection: 'row', body: flex: 18, justifyContent: 'spazio-tra', padding: 10, marginTop: 20);

Prova l'app

Dal momento che il tuo server di sviluppo di Expo è in esecuzione da un po 'di tempo, ogni modifica deve essere trasferita sul tuo dispositivo mobile con il caricamento in tempo reale. Prova l'app e assicurati che funzioni come dovrebbe.

Conclusione

Questo è tutto! In questo tutorial hai imparato come utilizzare Expo XDE per collegare rapidamente un'app React Native. Expo è un ottimo modo per iniziare a sviluppare app React Native perché elimina la necessità di installare un sacco di software che è spesso causa di frustrazione, soprattutto per i principianti. Fornisce inoltre strumenti che facilitano notevolmente l'anteprima dell'app durante lo sviluppo. Assicurati di controllare le risorse menzionate sul sito di Expo se vuoi saperne di più.

E nel frattempo, dai uno sguardo ad alcuni dei nostri altri post sullo sviluppo di app React Native!