Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. React Native

Viết một Ứng dụng với GraphQL, React Native và AWS AppSync: Phần Ứng dụng

by
Difficulty:IntermediateLength:LongLanguages:

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)

Final product image
What You'll Be Creating

Trong các bài này, tôi sẽ hướng dẫn cho bạn cách tạo và tương tác với cơ sở dữ liệu GraphQL bằng AWS AppSync và React Native. Ứng dụng này sẽ có chức năng thời gian thực và offline, là thứ được hỗ trợ bởi AppSync.

Trong bài trước, chúng ta đã thiết lập back-end GraphQL với dịch vụ Amazon AppSync. Hãy đọc nó nếu bạn chưa đọc. Hoặc, nếu bạn muốn một bài giới thiệu về GraphQL, hãy đọc một số bài viết khác của chúng tôi.

Trong bài viết này, chúng ta sẽ tổng hợp tất cả lại bằng cách bắt đầu xây dựng phần client của ứng dụng React Native. Dự án hơi phức tạp một chút, nhưng ta sẽ giải thích cấu trúc của dự án và cho bạn thấy các phần quan trọng của mã nguồn.

Tổng quan về Kiến trúc của ứng dụng và Cấu trúc thư mục

Ứng dụng của chúng ta sẽ có một màn hình ban đầu sẽ bao gồm hai view dạng tab. Một tab sẽ liệt kê các thành phố từ cơ sở dữ liệu GraphQL, tab còn lại sẽ là form nhập liệu để thêm một thành phố mới. Tab Cities sẽ là một thanh điều hướng cho phép người dùng điều hướng đến các thành phố riêng lẻ.

Chúng ta sẽ lưu trữ các thành phần chính trong thư mục source, và sẽ có các thư mục khác trong thư mục src để giữ các mutation, truy vấn và subscription của GraphQL.

Chúng ta cũng sẽ có một thư mục assets để chứa hình ảnh của chúng ta.

folder structure

Tạo và Cấu hình Client cho React Native

Để dễ theo dõi, hãy xem mã nguồn hoàn chỉnh cho ứng dụng này trong repo GitHub của hướng dẫn, nhưng tôi sẽ phác thảo một số bước mà tôi đã thực hiện để tạo ứng dụng từ đầu.

Trước tiên, chúng tôi đã tạo một ứng dụng React Native mới sử dụng cả Expo.

Một khi dự án mới được tạo ra, chúng ta cài đặt các phụ thuộc. Đối với chức năng GraphQL và AppSync, chúng ta đã sử dụng các phụ thuộc sau:

Chúng ta còn sử dụng các phụ thuộc sau đây cho thiết kế giao diện người dùng:

Ngoài ra, một thư viện Icon vector đã được cài đặt, chúng ta liên kết với nó:

Sau khi cài đặt các phụ thuộc, chúng ta tải về tập tin AppSync.js từ console của AppSync. Trong console của dự án AppSync, chúng ta chọn React Native ở phía dưới cùng và nhấp vào nút Download màu cam để tải về tập tin cấu hình này.


Tập tin cấu hình này nắm giữ thông tin client của AppSync mà chúng ta cần để tạo một client mới.

Cấu hình Provider và Store

Level cao nhất của ứng dụng là nơi mà chúng ta sẽ thực hiện cấu hình để kết nối API AppSync với client React Native. Nếu bạn đã từng sử dụng Redux hoặc React Apollo trước đây, thì bạn sẽ thấy rất quen. Nếu bạn chưa, chỉ cần nhớ rằng bất kỳ con nào của Provider, trong trường hợp của chúng ta ApolloProvider, sẽ có quyền truy cập vào các chức năng nhất định của nó.

Code sau đây là tập tin App.js mới của chúng ta, là thành phần chính được import từ tập tin index.js.

Trong tập tin này, chúng ta thiết lập một client AppSync mới bằng cách sử dụng tổ hợp constructor AWSAppSyncClient từ aws-appsync cũng như cấu hình trong tập tin aws-exports.js của chúng ta, cung cấp URL của API GraphQL, vùng, kiểu chứng thực và khóa API xác thực.

Sau đó chúng ta sẽ gói entry point chính, tập tin Tabs.js sẽ giữ tab điều hướng của chúng ta, trong một ApolloProvider và truyền vào client AppSync dưới dạng client prop. Chúng ta cũng gói thành phần Tabs trong thành phần Rehydrated mà chúng ta import từ aws-appsync-react. Điều này sẽ đảm bảo rằng chúng ta đã đọc từ bộ nhớ async và đã hoàn lại bộ nhớ cache trước khi kết xuất giao diện người dùng.

Bây giờ ứng dụng của chúng ta sẽ có thể truy vấn dữ liệu từ endpoint AppSync và cũng thực hiện mutation và subscription!

Điều hướng

Entry point chính của ứng dụng là một thanh điều hướng dạng tab, được cài đặt trong tập tin Tabs.js bằng React Navigation.

Những gì chúng ta đã làm ở đây là tạo và xuất một TabNavigator với hai tab. Đó là:

  1. Cities - Thành phần này liệt kê các thành phố của chúng ta, và nó là một thành phần chính trong và của chính nó. Thành phần này là thanh điều hướng bởi vì chúng ta muốn có thể điều hướng đến từng thành phố riêng lẻ và xem các địa điểm trong thành phố.
  2. AddCity - Thành phần này là một form để chúng ta có thể thêm các thành phố mới.

Các thành phần có thể tái sử dụng

Ứng dụng này chỉ có một thành phần có thể tái sử dụng, một TextInput tùy biến. Vì chúng ta sẽ nhân đôi style và chức năng nhiều lần, chúng ta quyết định biến nó trở thành thành phần riêng của nó. Thành phần input này được cài đặt trong Input.js.

Danh sách Thành phố và Điều hướng Thành phố

View chính của ứng dụng là một danh sách các thành phố mà chúng ta sẽ truy xuất từ ​​GraphQL. Chúng ta muốn khả năng điều hướng từ mỗi thành phố được liệt kê đến một view chi tiết về thành phố đó, nơi chúng ta có thể thêm các địa điểm.

Để làm điều này, chúng ta làm cho Cities.js trở nên của riêng StackNavigator và City.js thành phần mà chúng ta điều hướng đến khi chọn một thành phố. Khi nhấp vào một thành phố trong Cities, chúng ta truyền tên và id của địa điểm của nó dưới dạng props đến City.

Cities.js

Trong thành phần này, chúng ta truy xuất bằng truy vấn listCities, và chúng tôi cũng đăng ký vào NewCitySubscription, do đó khi một thành phố mới được thêm vào, ngay cả từ một client khác, chúng ta sẽ xử lý subscription đó và cập nhật mảng các thành phố của chúng ta. Truy vấn listCities tạo ra một mảng các thành phố hiện diện trong thành phần của chúng ta dưới dạng this.props.cities.

City.js

Trong thành phần này, chúng ta truyền một thành phố dưới dạng props từ navigation (dưới dạng props.navigation.state.params.city). Chúng ta sử dụng giá trị id của thành phố để lấy về danh sách các vị trí của thành phố đã chọn bằng truy vấn listLocations. Chúng ta đăng ký các địa điểm mới theo cách tương tự mà chúng ta đã đăng ký với các thành phố mới trong Cities.js, bằng subscription NewLocationSubscription. Chúng ta còn cung cấp một chức năng optimisticResponse & update khi một thành phố mới được thêm vào.

Thêm thành phố

Cuối cùng, chúng ta cần cài đặt tính năng để thêm các thành phố mới vào GraphQL API của chúng ta trong tập tin AddCity.js. Để làm điều này, chúng ta đã tạo ra một mutatioin cùng với một form mà sẽ gọi createCity, truyền giá trị của form nhập liệu.

AddCity có một hàm onAdd mà chúng ta định nghĩa trong thành phần GraphQL của chúng ta, không chỉ ghi một thành phố mới vào trong cơ sở dữ liệu GraphQL mà còn cài đặt một giao diện optimistic bằng cách sử dụng một sự kết hợp của optimisitcResponseupdate.

Mutation, Truy vấn và Subscription

Mutation, truy vấn và subscription là các chức năng cốt lõi để tích hợp với GraphQL API. Trong ứng dụng của chúng ta, chức năng này được cài đặt trong các tập tin Cities.js, City.jsAddCity.js bằng client AppSync.

Hãy tìm hiểu kỹ hơn về cách những mutation, truy vấn và subscription được cài đặt trong code của chúng ta.

Truy vấn

Trước tiên, hãy xem cách tạo và xuất một truy vấn GraphQL có thể tương tác với truy vấn listCities trong Lược đồ AppSync của chúng ta. Code này được chứa trong tập tin src/queries/LIstCities.js.

Tiếp theo, chúng ta import truy vấn này vào tập tin Cities.js cùng với một số helper từ react-apollo và kết nối thành phần mà chúng ta muốn có quyền truy cập vào dữ liệu này bằng composegraphql từ react-apollo.

Bây giờ chúng ta đã có quyền truy cập vào mảng các thành phố từ máy chủ GraphQL của chúng ta dưới dạng một prop. Chúng ta có thể sử dụng this.props.cities để ánh xạ mảng của các thành phố đến từ GraphQL.

Mutation

Để tạo ra một mutation, trước tiên chúng ta cần phải tạo ra một mutation cơ bản của GraphQL và xuất nó. Chúng tôi thực hiện việc này trong tập tin src/mutations/CreateCity.js.

Bây giờ chúng ta có thể import mutation này (cùng với helper Apollo) trong tập tin AddCity.js và sử dụng nó trong một thành phần:

Bây giờ chúng ta đã có quyền truy cập vào một prop được gọi là onAdd, cái mà chúng ta truyền vào một đối tượng mà chúng ta muốn gửi đến mutation!

Subscription

Subscription cho phép chúng ta đăng ký các thay đổi dữ liệu và cập nhật chúng trong ứng dụng của chúng ta theo thời gian thực. Nếu chúng ta thay đổi cơ sở dữ liệu của chúng ta bằng cách thêm hoặc xóa một thành phố, chúng ta muốn ứng dụng của chúng ta cập nhật theo thời gian thực.

Đầu tiên chúng ta cần tạo ra mutation và xuất nó để chúng ta có thể truy cập đến nó bên trong client. Chúng ta lưu nó trong tập tin src/subscriptionsNewCitySubscriptions.js.

Bây giờ chúng ta có thể import và đính kèm subscription trong Cities.js. Chúng ta đã tìm hiểu cách để lấy được các thành phố từ API của chúng ta. Hãy cập nhật chức năng này để đăng ký các thay đổi mới và cập nhật mảng các thành phố khi một thành phố mới được thêm vào.

Chúng ta thêm một prop mới gọi là subscribeToNewCities, cái mà chúng ta gọi trong componentDidMount. Trong subscription, chúng ta truyền vào một tài liệu (định nghĩa subscription) và updateQuery để mô tả những gì chúng ta muốn xảy ra điều này cập nhật.

Chúng ta hủy cấu trúc createCity (chứa mutation) từ props được truyền vào trong hàm updateQuery và trả về tất cả các giá trị hiện có cùng với mảng mảng listCities đã cập nhật chứa các thành phố trước đó cùng với dữ liệu thành phố mới mà chúng ta nhận được từ createCity.

Optimistic UI

Điều gì sẽ xảy ra nếu chúng ta không muốn đợi subscription trả về dữ liệu cập nhật mới nhất từ ​​API của chúng ta để cập nhật UI?

Nếu người dùng tạo một thành phố mới, chúng tôi muốn tự động thêm nó vào mảng cities và kết xuất nó trong ứng dụng của chúng ta trước khi nhận được xác nhận từ dịch vụ back-end.

Chúng ta có thể làm điều đó một cách dễ dàng bằng cách sử dụng một vài kỹ thuật và hàm.

Hãy cập nhật AddCityMutation của chúng ta như sau (bạn có thể xem code này trong tập tin AddCity.js):

Ở đây, chúng ta đã thêm hai thuộc tính mới vào đối tượng đối số của hàm mutation:

  1. optimisticResponse định nghĩa phản hồi mới mà bạn muốn có trong hàm cập nhật
  2. update nhận hai đối số, proxy (cho phép bạn đọc từ bộ nhớ cache) và dữ liệu bạn muốn sử dụng để cập nhật. Chúng ta đọc bộ nhớ cache hiện tại (proxy.readQuery), thêm phần tử mới vào mảng các phần tử, sau đó ghi ngược trở lại bộ nhớ cache, sẽ cập nhật giao diện người dùng của chúng ta.

Tóm tắt

GraphQL ngày càng trở nên phổ biến. Phần lớn sự phức tạp xoay quanh GraphQL có liên quan đến quản lý back-end và lớp API. Tuy nhiên, các công cụ như AppSync đơn giản hóa sự phức tạp này, giải phóng các nhà phát triển khỏi việc dành hầu hết thời gian để cấu hình và làm việc trên máy chủ.

Tôi muốn nhìn thấy nhiều sáng kiến mới trong lĩnh vực này, và không thể chờ đợi để xem những gì chúng ta sẽ thấy trong năm 2018!

Nếu bạn quan tâm đến việc sử dụng AppSync cùng với framework Serverless, hãy xem phần giới thiệu tuyệt vời này để sử dụng cả hai cùng với nhau.

Nếu bạn muốn tìm hiểu thêm về AWS AppSync, tôi đề nghị bạn truy cập trang chủ AppSynchướng dẫn để xây dựng một client GraphQL.

Nếu bạn muốn đóng góp cho dự án này, bạn có thể kết nối với repo GitHub của chúng tôi. Nếu bạn có bất kỳ ý tưởng nào, vui lòng gửi cho chúng tôi một PR hoặc sử dụng ứng dụng này làm tiền đề cho dự án React Native GraphQL tiếp theo của bạn!

Và trong lúc chờ đợi, hãy tìm hiểu một số hướng dẫn React Native khác của chúng tôi ở đây trên Envato Tuts+!

Advertisement
Advertisement
Advertisement
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.