Codifica un'app con GraphQL, React Native e AWS AppSync l'app

Cosa starai creando

In questi tutorial, ti sto mostrando come creare e interagire con un database GraphQL usando AWS AppSync e React Native. Questa app avrà funzionalità in tempo reale e offline, qualcosa che uscirà dalla confezione con AppSync. 

Nel post precedente, abbiamo configurato il nostro back-end GraphQL con il servizio Amazon AppSync. Controllalo se non l'hai già fatto. Oppure, se vuoi un'introduzione a GraphQL, dai un'occhiata ad alcuni dei nostri altri post.

In questo post, completeremo tutto attraverso la creazione del client React Native. Il progetto è un po 'troppo complicato per guidarti passo dopo passo, ma ti spiegherò l'architettura del progetto e ti mostrerò le parti chiave del codice sorgente.

Panoramica sull'architettura dell'app e sulla struttura delle cartelle

La nostra applicazione avrà un punto di ingresso principale che consisterà in due viste a schede. Una scheda elencherà le città dal nostro database GraphQL e l'altra sarà il modulo di immissione per aggiungere una nuova città. Il Città scheda sarà un navigatore che permetterà all'utente di navigare verso le singole città.

Conserveremo i componenti principali nel fonte cartella e avrà altre cartelle nel src directory per contenere le nostre mutazioni GraphQL, query e iscrizioni.

Avremo anche un risorse cartella per contenere le nostre immagini.

Creazione e configurazione di React Native Client

Per riferimento, dai un'occhiata al codice finale di questa app nel tutorial sul repository GitHub, ma descriverò alcuni dei passaggi che ho seguito per creare l'app da zero.

Innanzitutto, abbiamo creato una nuova applicazione React Native usando Expo. 

Una volta nel progetto appena creato, abbiamo installato le nostre dipendenze. Per la funzionalità GraphQL e AppSync, abbiamo utilizzato le seguenti dipendenze:

aws-appsync aws-appsync-react graphql-tag react-apollo uuid

Abbiamo anche utilizzato le seguenti dipendenze per la progettazione dell'interfaccia utente:

react-navigation react-native-elements react-native-vector-icons

Inoltre, una volta installata la libreria Vector Icons, l'abbiamo collegata:

react-native link react-native vector-icons

Dopo aver installato le nostre dipendenze, abbiamo scaricato il AppSync.js file dalla nostra console AppSync. Nella nostra console di progetto AppSync, abbiamo scelto Reagire Nativo in basso, e fatto clic sull'arancio Scaricare pulsante per scaricare questo file di configurazione.


Questo file di configurazione contiene le informazioni del client AppSync necessarie per creare un nuovo client. 

Configurazione del provider e dello store

Il livello più alto dell'app è dove faremo la nostra configurazione per cablare l'API AppSync con il client React Native.Se hai già usato Redux o React Apollo, questo sarà familiare. Se non lo hai fatto, ricorda che qualsiasi figlio di a Provider, nel nostro caso il ApolloProvider, avrà accesso alle sue funzionalità fornite. 

Il seguente codice è il nostro nuovo App.js file, che è il componente principale importato dal nostro index.js punto d'entrata.

import Reagire dalle schede di importazione 'react' da './src/Tabs' importare AWSAppSyncClient da "aws-appsync"; importare Rehydrated da 'aws-appsync-react'; import ApolloProvider da 'react-apollo'; importare appSyncConfig da './aws-exports'; const client = new AWSAppSyncClient (url: appSyncConfig.graphqlEndpoint, region: appSyncConfig.region, auth: type: appSyncConfig.authType, apiKey: appSyncConfig.apiKey,); const WithProvider = () => (      ); esportazione predefinita WithProvider

In questo file, stiamo impostando un nuovo client AppSync usando una combinazione di AWSAppSyncClient costruttore da AWS-AppSync così come la configurazione nel nostro AWS-exports.js file, che fornisce l'URL dell'API GraphQL, la regione, il tipo di autenticazione e la chiave API di autenticazione.

Quindi avvolgiamo il nostro principale punto di accesso, il Tabs.js file che manterrà il nostro tab di navigazione, in un file ApolloProvider e passare il client AppSync come il prop client. Abbiamo anche avvolto il Tabs componente in a reidratato componente da cui importiamo AWS-AppSync-reagire. Ciò assicurerà di aver letto dalla memoria asincrona e di aver reidratato la nostra cache prima di rendere l'interfaccia utente.

Ora la nostra app sarà in grado di interrogare i dati dal nostro endpoint AppSync e anche di eseguire mutazioni e abbonamenti!

Navigazione

Il punto di accesso principale dell'app è una navigazione a schede, implementata nel file Tabs.js con React Navigation.

Quello che abbiamo fatto qui è creare ed esportare a TabNavigator con due schede. Questi sono:

  1. Città: Questo componente elenca le nostre città, ed è un componente del navigatore in sé e per sé. Questo componente è un navigatore perché vogliamo essere in grado di navigare verso ogni singola città e visualizzare le posizioni all'interno della città.
  2. AddCity: Questo componente è un modulo per noi per poter aggiungere nuove città.

Componenti riutilizzabili

Questa app ha un solo componente riutilizzabile, personalizzato L'immissione di testo. Dal momento che duplicheremo continuamente questo stile e questa funzionalità, abbiamo deciso di renderlo un suo componente. Il componente di input è implementato in Input.js.

Lista delle città e della città

La vista principale dell'app è una lista di città che recupereremo da GraphQL. Vogliamo essere in grado di navigare da ciascuna città elencata a una vista di dettaglio di quella città in cui possiamo aggiungere posizioni.

Per fare questo, facciamo Cities.js il proprio StackNavigator e City.js il componente a cui navighiamo quando si sceglie una città. Quando si fa clic su una città in Città, noi passiamo il suo nome e il suo nome come oggetto di riferimento Città.

Cities.js

In questo componente, stiamo recuperando usando il listCities query, e ci stiamo anche iscrivendo al NewCitySubscription, in modo che quando viene aggiunta una nuova città, anche da un altro cliente, gestiremo tale abbonamento e aggiorneremo la nostra serie di città. Il listCities query rende disponibile una serie di città nel nostro componente come this.props.cities.

City.js

In questo componente, siamo passati una città come oggetti di scena dalla navigazione (disponibile come props.navigation.state.params.city). Usiamo la città id valore per recuperare l'elenco delle posizioni per la città scelta utilizzando il listLocations query. Ci iscriviamo a nuove sedi in modo simile a come ci iscriviamo alle nuove città in Cities.js, usando il NewLocationSubscription sottoscrizione. Forniamo anche optimisticResponseaggiornare funzioni per quando viene aggiunta una nuova città. 

Aggiungere città

Infine, dobbiamo implementare la funzionalità per aggiungere nuove città alla nostra API GraphQL nel file AddCity.js. Per fare ciò, abbiamo cablato una mutazione insieme a un modulo che chiamerà createCity, passando il valore del modulo di input.

AddCity ha un onAdd funzione che definiamo nella nostra composizione GraphQL, che non solo scrive una nuova città nel nostro database GraphQL, ma implementa anche un'interfaccia utente ottimistica usando una combinazione di optimisticResponse e aggiornare.

Mutazioni, query e iscrizioni

Mutazioni, query e abbonamenti sono le funzionalità principali per l'integrazione con la nostra API GraphQL. Nella nostra app, questa funzionalità è implementata nel Cities.js, City.js, e AddCity.js file usando il client AppSync.

Diamo un'occhiata più da vicino a come le mutazioni, le query e gli abbonamenti sono implementati nel nostro codice.

Interrogazioni

Per prima cosa, diamo un'occhiata a come creare ed esportare una query GraphQL che potrebbe interagire con listCities interrogare nel nostro schema AppSync. Questo codice è contenuto nel src / Query / ListCities.js file.

importare gql da 'graphql-tag'; esporta gql predefinito 'query listCities listCities items name country id' 

Successivamente, importiamo questa query nel file Cities.js file, insieme ad alcuni aiutanti di reagire-apollo, e collegare il componente che vorremmo avere accesso a questi dati usando comporre e graphql a partire dal reagire-apollo.

import compose, graphql da 'react-apollo' import ListCities dalla classe './queries/ListCities' Cities estende React.Component // la definizione della classe qui // ora ha accesso a this.props.cities esporta la composizione predefinita ( graphql (ListCities, props: props => (cities: props.data.listCities? props.data.listCities.items: [],))) (CityList)

Ora abbiamo accesso alla matrice di città dal nostro server GraphQL come supporto. Possiamo usare this.props.cities mappare sulla matrice di città proveniente da GraphQL.

mutazioni

Per creare una mutazione, prima dobbiamo creare una mutazione GraphQL di base ed esportarla. Lo facciamo nel src / mutazioni / CreateCity.js file.

import gql da 'graphql-tag' export default gql 'addCity di mutazione ($ name: String !, $ country: String !, $ id: ID!) createCity (input: nome: $ nome, paese: $ paese, id : $ id) nome paese ID ' 

Ora possiamo importare questa mutazione (insieme agli aiutanti di Apollo) nel AddCity.js file e usarlo in un componente: 

import compose, graphql da 'react-apollo' import AddCityMutation dalla classe './mutations/AddCity' AddCity estende React.Component // class definition here // ora ha accesso a this.props.onAdd () default di esportazione componi (graphql (AddCityMutation, props: props => (onAdd: city => props.mutate (variables: city)))) (AddCity) 

Ora, abbiamo accesso a un supporto chiamato onAdd, che passiamo a un oggetto che vorremmo inviare alla mutazione!

Sottoscrizioni

Le iscrizioni ci consentono di sottoscrivere le modifiche ai dati e di aggiornarle nella nostra applicazione in tempo reale. Se dovessimo modificare il nostro database aggiungendo o rimuovendo una città, vorremmo che la nostra app si aggiornasse in tempo reale.

Per prima cosa, dobbiamo creare la mutazione ed esportarla in modo che possiamo avere accesso ad essa all'interno del client. Lo salviamo nel src / subscriptionsNewCitySubscriptions.js file.

importare gql dalla sottoscrizione 'graphql-tag' export default gql 'NewCitySub onCreateCity name country id'; 

Ora possiamo importare e allegare l'abbonamento in Cities.js. Abbiamo già visto come ottenere le città dalla nostra API. Aggiungiamo ora questa funzionalità per iscriversi alle nuove modifiche e aggiornare l'array delle città quando viene aggiunta una nuova città.

import AllCity da './queries/AllCity' import NewCitiesSubscription da './subscriptions/NewCitySubscription'; import compose, graphql dalla classe 'react-apollo' Cities estende React.Component componentWillMount () this.props.subscribeToNewCities ();  render () // resto del componente qui export compose predefinito (graphql (ListCities, options: fetchPolicy: 'cache-and-network', props: (props =) = return cities: props. data.listCities? props.data.listCities.items: [], subscribeToNewCities: params => props.data.subscribeToMore (document: NewCitiesSubscription, updateQuery: (precedente, subscriptionData: data: onCreateCity) = > return ... prev, listCities: __typename: 'CityConnection', articoli: [onCreateCity, ... prev.listCities.items.filter (city => city.id! == onCreateCity.id)]   ) )(Città)

Aggiungiamo un nuovo sostegno chiamato subscribeToNewCities, che chiamiamo componentDidMount. Nell'abbonamento, passiamo un documento (la definizione dell'abbonamento) e updateQuery per descrivere cosa vogliamo accadere quando questo si aggiorna.

Distruggiamo createCity (contenente la mutazione) dai sostegni che sono passati nel updateQuery funzione, e restituisce tutti i valori esistenti insieme a un aggiornamento listCities  array contenente le città precedenti insieme ai nuovi dati sulla città che otteniamo createCity.

UI ottimista

Cosa succede se non vogliamo aspettare che l'abbonamento restituisca i dati più aggiornati dalla nostra API per aggiornare la nostra interfaccia utente?

Se un utente crea una nuova città, vogliamo aggiungerla automaticamente all'array delle città e visualizzarla nella nostra app prima di ricevere la conferma dal servizio di back-end.

Possiamo farlo facilmente usando alcune tecniche e funzioni.

Aggiorniamo il nostro AddCityMutation al seguente (è possibile visualizzare questo codice nel file di origine AddCity.js):

import compose, graphql da 'react-apollo' import AddCityMutation dalla classe './mutations/AddCity' AddCity estende React.Component // class definition here // ora ha accesso a this.props.onAdd () default di esportazione compose (graphql (AddCityMutation, props: props => (onAdd: city => props.mutate (variables: city, optimisticResponse: __typename: 'Mutation', createCity: ... city, __typename: 'City' , aggiornamento: (proxy, data: createCity) => const data = proxy.readQuery (query: ListCities); data.listCities.items.unshift (createCity); proxy.writeQuery (query: ListCities , dati);)))) (AggiungiCittà) 

Qui, abbiamo aggiunto due nuove proprietà all'oggetto argomento della funzione mutate:

  1. optimisticResponse definisce la nuova risposta che vorresti avere disponibile nella funzione di aggiornamento.
  2. aggiornare accetta due argomenti, il proxy (che consente di leggere dalla cache) e i dati che si desidera utilizzare per effettuare l'aggiornamento. Leggiamo la cache corrente (proxy.readQuery), aggiungilo alla nostra serie di elementi e poi riscrivilo nella cache, che ha aggiornato la nostra interfaccia utente.

Conclusione

GraphQL sta diventando sempre più mainstream. Gran parte della complessità che circonda GraphQL ha a che fare con la gestione del back-end e del livello API. Tuttavia, strumenti come AppSync eliminano questa complessità, liberando gli sviluppatori dal passare la maggior parte del tempo a configurare e lavorare sul server.

Attendo con ansia molte più innovazioni in questo spazio e non vedo l'ora di vedere cos'altro vedremo nel 2018!

Se sei interessato all'utilizzo di AppSync insieme al framework Serverless, dai un'occhiata a questa fantastica introduzione sull'utilizzo di entrambi.

Se vuoi saperne di più su AWS AppSync, ti suggerisco di dare un'occhiata alla homepage di AppSync e alla documentazione per creare un client GraphQL.

Se vuoi contribuire a questo progetto, puoi connetterti al nostro repository GitHub. Se avete qualche idea, sentitevi liberi di inviarci un PR o utilizzare questa app come base per il vostro prossimo progetto React Native GraphQL!

E nel frattempo, dai uno sguardo agli altri tutorial di React Native qui su Envato Tuts+!