Advertisement
  1. Code
  2. React Native

Code App dengan GraphQL, React Native dan AWS AppSync: App

Scroll to top
Read Time: 11 min

Indonesian (Bahasa Indonesia) translation by Ilham Saputra (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Dalam tutorial ini, saya akan menunjukkan cara membuat dan berinteraksi dengan database GraphQL menggunakan AWS AppSync dan React Native. Aplikasi ini akan memiliki fungsionalitas offline real-time *, sesuatu yang kita dapatkan dari kotak dengan AppSync.

Di posting sebelumnya kami menyiapkan back-end GraphQL kami dengan layanan Amazon AppSync. Coba lihat jika Kamu belum melakukannya. Atau, jika Kamu ingin di perkenalan dengan GraphQL, lihat beberapa tulisan kami yang lain.

Dalam tulisan ini, kita akan membungkus semuanya dengan berjalan melalui membangun klien React Native. Proyek ini agak terlalu rumit untuk ditunjukkan padamu melalui langkah demi langkah, tapi saya akan menjelaskan arsitektur proyek dan menunjukkan bagian penting dari source code.

Ikhtisar Arsitektur App dan Struktur Folder

Aplikasi kami akan memiliki entry point utama yang terdiri dari dua tampilan tab. Satu tab akan mencantumkan kota-kota dari database GraphQL kami, yang lainnya akan menjadi bentuk masukan untuk menambahkan kota baru. Tab Cities akan menjadi navigator yang memungkinkan pengguna menavigasi ke masing-masing kota.

Kami akan menyimpan komponen utama di source folder, dan akan memiliki folder lain di direktori src untuk menahan mutations, queries, dan subscriptions GraphQL kami.

Kami juga akan memiliki folder aset untuk menampung gambar kami.

folder structure

Membuat dan Mengkonfigurasi Klien React Native

Sebagai referensi, lihat kode akhir untuk aplikasi ini di tutorial GitHub repo, tapi saya akan menjelaskan beberapa langkah yang saya ambil untuk membuat aplikasi dari awal.

Pertama, kami membuat aplikasi React Native baru menggunakan Expo.

Begitupun dalam proyek yang baru dibuat, kami memasang dependensi kami. Untuk fungsionalitas GraphQL dan AppSync, kami menggunakan dependensi berikut ini:

1
aws-appsync
2
aws-appsync-react
3
graphql-tag
4
react-apollo
5
uuid

Kami juga menggunakan dependensi berikut untuk desain UI:

1
react-navigation
2
react-native-elements
3
react-native-vector-icons

Juga, satu perpustakaan Vector Icons telah terpasang, kami menghubungkannya:

1
react-native link react-native vector-icons

Setelah menginstal dependensi kami, kami mendownload file AppSync.js dari konsol AppSync kami. Di konsol proyek AppSync kami, kita pilih React Native di bagian bawah, dan mengeklik tombol Download oranye untuk mendownload file konfigurasi ini.


File konfigurasi ini menyimpan informasi klien AppSync yang kami butuhkan untuk membuat klien baru.

Mengkonfigurasi Provider dan Store

Tingkat atas aplikasi adalah tempat kami akan melakukan konfigurasi untuk memasang API AppSync dengan klien React Native. Jika Anda telah menggunakan Redux atau React Apollo sebelumnya, semua ini akan menjadi tidak asing lagi. Jika belum, ingatlah bahwa setiap anak Provider, dalam kasus kami ApolloProvider, akan memiliki akses ke fungsi yang diberikannya.

Kode berikut adalah file App.js baru kami, yang merupakan komponen utama yang diimpor dari titik masuk index.js kami.

1
import React from 'react'
2
import Tabs from './src/Tabs'
3
4
import AWSAppSyncClient from "aws-appsync";
5
import { Rehydrated } from 'aws-appsync-react';
6
import { ApolloProvider } from 'react-apollo';
7
8
import appSyncConfig from './aws-exports';
9
10
const client = new AWSAppSyncClient({
11
  url: appSyncConfig.graphqlEndpoint,
12
  region: appSyncConfig.region,
13
  auth: {
14
    type: appSyncConfig.authType,
15
    apiKey: appSyncConfig.apiKey,
16
  }
17
});
18
19
const WithProvider = () => (
20
  <ApolloProvider client={client}>
21
    <Rehydrated>
22
      <Tabs />
23
    </Rehydrated>
24
  </ApolloProvider>
25
);
26
27
export default WithProvider

Dalam file ini, kami menyiapkan klien AppSync baru menggunakan kombinasi konstruktor AWSAppSyncClient dari aws-appsync dan juga konfigurasi di file aws-exports.js kami, yang menyediakan URL API GraphQL, wilayah, jenis otentikasi, dan otentikasi API key.

Kami kemudian membungkus entrypoint utama kami, file Tabs.js yang akan menahan tab navigasi kami, di ApolloProvider dan masuk ke klien AppSync sebagai prop klien. Kami juga membungkus komponen Tabs dalam komponen Rehydrated yang kami impor dari aws-appsync-react. Ini akan memastikan bahwa kita telah membaca dari penyimpanan async dan telah mengosongkan cache kita sebelum merender UI.

Sekarang aplikasi kami akan dapat melakukan kueri data dari titik akhir AppSync kami, dan juga untuk melakukan mutations dan subscriptions!

Navigasi

Titik masuk utama aplikasi adalah tab navigasi, yang diterapkan pada file Tabs.js dengan React Navigation.

Apa yang telah kami lakukan di sini adalah membuat dan mengekspor TabNavigator dengan dua tab. Ini adalah:

  1. Cities - Komponen ini mencantumkan kota kita, dan ini menjadi komponen navigator dalam dan dari dirinya sendiri. Komponen ini adalah navigator karena kita ingin bisa menavigasi ke masing-masing kota dan melihat lokasi di dalam kota.
  2. AddCity - Komponen ini merupakan form bagi kita untuk bisa menambah kota baru.

Komponen Reusable

Aplikasi ini hanya memiliki satu komponen reusable, TextInput yang disesuaikan. Karena kita akan menduplikasi gaya dan fungsi ini berulang-ulang, kami memutuskan untuk menjadikannya komponennya sendiri. Komponen masukan diimplementasikan di Input.js.

Cities List dan City Navigation

Tampilan utama dari aplikasi ini adalah daftar kota yang akan kita ambil dari GraphQL. Kami ingin dapat menavigasi dari setiap kota yang terdaftar ke tampilan detail kota tempat kami dapat menambahkan lokasi.

Untuk melakukan ini, kami menjadikan Cities.js sebagai StackNavigator miliknya sendiri, dan City.js komponen yang kami navigasikan saat memilih kota. Saat mengklik sebuah kota di Cities, kami melewati namanya dan id sebagai alat peraga untuk City.

Cities.js

Dalam komponen ini, kami menarik menggunakan query listCities, dan kami juga berlangganan NewCitySubscription, sehingga ketika sebuah kota baru ditambahkan, bahkan dari klien lain, kami akan menangani langganan tersebut dan memperbarui jajaran kota kami. Query listCities membuat berbagai kota yang tersedia di komponen kami sebagai this.props.cities.

City.js

Dalam komponen ini, kita melewati sebuah kota sebagai props dari navigasi (tersedia sebagai props.navigation.state.params.city). Kami menggunakan nilai id kota untuk mengambil daftar lokasi untuk kota yang dipilih menggunakan query listLocations. Kami berlangganan lokasi baru dengan cara yang sama seperti kami berlangganan kota baru di Cities.js, menggunakan langganan NewLocationSubscription. Kami juga menyediakan fungsi update & optimisticResponse untuk saat sebuah kota baru ditambahkan. Respons yang optimis

Menambahkan Cities

Akhirnya, kita perlu menerapkan fungsi untuk menambahkan kota baru ke API GraphQL kami di file AddCity.js. Untuk melakukan ini, kita telah menghubungkan mutation dengan bentuk yang akan memanggil createCity, melewati nilai input form.

AddCity memiliki fungsi onAdd yang kami definisikan dalam komposisi GraphQL kami, yang tidak hanya menulis sebuah kota baru ke database GraphQL kami, namun juga mengimplementasikan UI yang optimis dengan menggunakan kombinasi optimisitcResponse dan update.

Mutations, Queries, dan Subscriptions

Mutations, queries, dan subscriptions adalah fungsi inti untuk mengintegrasikan API GraphQL kami. Di aplikasi kami, fungsi ini diterapkan di file Cities.js, City.js, dan AddCity.js menggunakan klien AppSync.

Mari kita lihat lebih dekat bagaimana mutation, query, dan subscriptions diterapkan dalam kode kita.

Queries

Pertama, mari kita lihat cara membuat dan mengekspor query GraphQL yang dapat berinteraksi dengan listCities query di Skema AppSync kami. Kode ini terdapat dalam file src/queries/LIstCities.js.

1
import gql from 'graphql-tag';
2
3
export default gql`

4
query listCities {

5
  listCities  {

6
    items {

7
      name

8
      country

9
      id

10
    }

11
  }

12
}`

Selanjutnya, kami mengimpor query ini di file Cities.js, bersama dengan beberapa penunjang dari react-apollo, dan memasang komponen yang ingin kami akses ke data ini menggunakan compose dan graphql dari react-apollo.

1
import { compose, graphql } from 'react-apollo'
2
import ListCities from './queries/ListCities'
3
4
class Cities extends React.Component {
5
  // class definition here

6
  // now have access to this.props.cities

7
}
8
9
export default compose(
10
  graphql(ListCities, {
11
      props: props => ({
12
        cities: props.data.listCities ? props.data.listCities.items : [],
13
      })
14
  })
15
)(CityList)

Sekarang kita memiliki akses ke deretan kota dari server GraphQL kita sebagai prop. Kita dapat menggunakan this.props.cities untuk memetakan deretan kota yang masuk dari GraphQL.

Mutations

Untuk membuat mutations, pertama kita perlu membuat mutasi GraphQL dasar dan mengekspornya. Kami melakukan ini di file src/mutations/CreateCity.js.

1
import gql from 'graphql-tag'
2
3
export default gql`

4
  mutation addCity($name: String!, $country: String!, $id: ID!) {

5
    createCity(input: {

6
      name: $name, country: $country, id: $id

7
    }) {

8
      name

9
      country

10
      id

11
    }

12
  }

13
`

Baru kita bisa mengimpor mutasi ini (bersama dengan pembantu Apollo) di file AddCity.js dan menggunakannya dalam sebuah komponen:

1
import { compose, graphql } from 'react-apollo'
2
import AddCityMutation from './mutations/AddCity'
3
4
class AddCity extends React.Component {
5
  // class definition here

6
  // now have access to this.props.onAdd()

7
}
8
9
export default compose(
10
  graphql(AddCityMutation, {
11
    props: props => ({
12
      onAdd: city => props.mutate({
13
        variables: city
14
      })
15
    })
16
  })
17
)(AddCity)

Sekarang, kita memiliki akses ke sebuah prop yang disebut onAdd, yang kita lewati sebuah objek yang ingin kita kirim ke mutasi!

Subscriptions

Subscriptions memungkinkan kami untuk berlangganan perubahan data dan memperbaruinya di aplikasi kami secara real time. Jika kami mengubah database kami dengan menambahkan atau menghapus kota, kami ingin agar aplikasi kami diperbarui secara real time.

Pertama kita perlu menciptakan mutasi dan mengekspornya sehingga kita bisa memiliki akses ke dalamnya di dalam klien. Kami simpan ini di file src/subscriptionsNewCitySubscriptions.js.

1
import gql from 'graphql-tag'
2
3
export default gql`

4
subscription NewCitySub {

5
  onCreateCity {

6
    name

7
    country

8
    id

9
  }

10
}`;

Sekarang kita bisa mengimpor dan melampirkan subscription di Cities.js. Kami sudah melihat bagaimana cara mendapatkan kota dari API kami. Mari sekarang perbarui fungsi ini untuk langganan perubahan baru dan memperbarui deretan kota saat kota baru ditambahkan.

1
import AllCity from './queries/AllCity'
2
import NewCitiesSubscription from './subscriptions/NewCitySubscription';
3
import { compose, graphql } from 'react-apollo'
4
5
6
class Cities extends React.Component {
7
  componentWillMount(){
8
    this.props.subscribeToNewCities();
9
  }
10
  render() {
11
    // rest of component here
12
  }
13
}
14
15
export default compose(
16
  graphql(ListCities, {
17
    options: {
18
      fetchPolicy: 'cache-and-network'
19
    },
20
    props: (props) => {
21
      return {
22
        cities: props.data.listCities ? props.data.listCities.items : [],
23
        subscribeToNewCities: params => {
24
          props.data.subscribeToMore({
25
            document: NewCitiesSubscription,
26
            updateQuery: (prev, { subscriptionData: { data : { onCreateCity } } }) => {
27
              return {
28
                ...prev,
29
                listCities: {
30
                  __typename: 'CityConnection',
31
                  items: [onCreateCity, ...prev.listCities.items.filter(city => city.id !== onCreateCity.id)]
32
                }
33
              }
34
            }
35
          })
36
        }
37
      }
38
    }
39
  })
40
)(Cities)

Kami menambahkan sebuah prop baru yang disebut subscribeToNewCities, yang kami sebut di componentDidMount. Dalam subscription, kami menyampaikan sebuah dokumen (definisi subscription) dan updateQuery untuk menjelaskan apa yang ingin kita lakukan saat update ini.

Kami mendekonstruksi createCity (berisi mutation) dari props yang masuk ke fungsi updateQuery, dan mengembalikan semua nilai yang ada beserta daftar listCities yang diperbarui yang berisi array cities sebelumnya beserta data kota baru yang kami dapatkan dari createCity.

Optimistic UI

Bagaimana jika kami tidak ingin menunggu subscription mengembalikan data terbaru dari API kami untuk memperbarui UI kami?

Jika pengguna membuat kota baru, kami ingin menambahkannya secara otomatis ke dalam array cities dan memilikinya di aplikasi kami sebelum menerima konfirmasi dari back-end service.

Kita bisa melakukannya dengan mudah menggunakan beberapa teknik dan fungsi.

Mari memperbarui AddCityMutation kami ke yang berikut ini (Anda dapat melihat kode ini di file sumber AddCity.js):

1
import { compose, graphql } from 'react-apollo'
2
import AddCityMutation from './mutations/AddCity'
3
4
class AddCity extends React.Component {
5
  // class definition here

6
  // now have access to this.props.onAdd()

7
}
8
9
export default compose(
10
  graphql(AddCityMutation, {
11
    props: props => ({
12
      onAdd: city => props.mutate({
13
        variables: city,
14
        optimisticResponse: {
15
          __typename: 'Mutation',
16
          createCity: { ...city,  __typename: 'City' }
17
        },
18
        update: (proxy, { data: { createCity } }) => {
19
          const data = proxy.readQuery({ query: ListCities });
20
          data.listCities.items.unshift(createCity);
21
          proxy.writeQuery({ query: ListCities, data });
22
        }
23
      })
24
    })
25
  })
26
)(AddCity)

Begini, kami telah menambahkan dua properti baru ke fungsi mutate objek argumen:

  1. optimisticResponse mendefinisikan respons baru yang ingin Anda miliki dalam fungsi update
  2. update membutuhkan dua argumen, proxy (yang memungkinkan Anda membaca dari cache) dan data yang ingin Anda gunakan untuk melakukan pembaruan. Kami membaca cache saat ini (proxy.readQuery), menambahkan item baru kami ke dalam array items, lalu menulis kembali ke cache, yang memperbarui UI kami.

Kesimpulan

GraphQL menjadi semakin utama. Sebagian besar kompleksitas seputar GraphQL berkaitan dengan pengelolaan backend dan API layer. Namun, alat seperti AppSync menghapuskan kompleksitas ini, membebaskan pengembang dari menghabiskan sebagian besar waktu mereka untuk mengkonfigurasi dan bekerja di server.

Saya berharap bisa lebih banyak inovasi di ruang ini, dan tidak sabar untuk melihat apa lagi yang akan kita lihat di tahun 2018!

Jika Anda tertarik untuk menggunakan AppSync bersamaan dengan Serverless, periksalah pengantar ini untuk menggunakan mereka berdua bersama-sama.

Jika Anda ingin mempelajari lebih lanjut tentang AWS AppSync, saya akan menyarankan untuk melihat homepage AppSync, dan dokumentasi untuk membangun klien GraphQL.

Jika Anda ingin berkontribusi pada proyek ini, Anda dapat terhubung ke repo GitHub kami. Jika Anda memiliki ide, silakan mengirimkan PR kepada kami, atau gunakan aplikasi ini sebagai starter untuk proyek React Native GraphQL Kamu berikutnya!

Dan sementara itu, lihat beberapa tutorial React Native kami yang lain di sini di Envato Tuts+!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.