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



AWS Amplify cho phép các nhà phát triển nhanh chóng xây dựng và kết nối với các dịch vụ mạnh mẽ trên cloud. Trong hướng dẫn trước, bạn đã học How to set up Amplify in a React project and how to use authentication, S3 storage, and hosting. Nếu bạn cần một giới thiệu về AWS Amplify, hãy nhớ xem bài viết đó trước.
Trong bài này, chúng ta sẽ tiếp tục với React và AWS Amplify, khám phá các tính năng như GraphQA data layer và các hàm lambda.
Tạo thêm một GraphQL API
Hãy xem làm sao để thêm vào một AWS AppSync GraphQL API vào dự án của chúng ta và bắt đầu sử dụng nó trong dự án.
API chúng tôi sẽ tạo sẽ là API cho restaurant để chúng tôi theo dõi các restaurant mà chúng tôi thích hoặc muốn ghé thăm.
Để thêm GraphQL API vào dự án, chúng ta có thể sử dụng lệnh sau đây:
amplify add api
Bạn sẽ được yêu cầu trả lời một số câu hỏi về cấu hình. Chọn các tùy chọn sau:
- service type: GraphQL
- API name: TutsGraphQLAPI
- authorization type: API key
- annotated GraphQL schema: N
- guided schema creation: Y
- Mô tả tốt nhất về dự án của bạn? Single object with fields (ví dụ: “Todo” with ID, name, description)
- Bạn có muốn chỉnh sửa schema ngay bây giờ không? Y
Khi được nhắc nhở, hãy cập nhật schema sau đây, rồi lưu file:
// located at amplify-web-app/amplify/backend/api/TutsGraphQLAPI/schema.graphql type Restaurant @model { id: ID! name: String! description: String }
Điều này chỉ tạo ra một data type (kiểu dữ liệu) duy nhất — Restaurant
— với id và name là bắt buộc, description là tuỳ chọn.
Tiếp theo, hãy push các cập nhật vào tài khoản của chúng ta:
amplify push
Bây giờ, API đã được tạo ra!
Chuyện gì vừa xảy ra ở đây? AWS Amplify sử dụng thư viện GraphQL Transform được xây dựng sẵn để tạo một GraphQL API hoàn chỉnh, bao gồm schema bổ sung, và data source.
Để xem API AppSync AWS mới bất kỳ lúc nào sau khi nó được tạo ra, bạn có thể truy cập dashboard (bảng điều khiển) tại https://console.aws.amazon.com/appsync và nhấp vào API vừa được tạo (đảm bảo rằng khu vực của bạn được thiết lập chính xác). Từ trong dashboard của AWS AppSync, bạn có thể xem cấu hình API và thực hiện các truy vấn và thay đổi trên API.
Thực hiện các thay đổi GraphQL
Tiếp theo, hãy tương tác với API từ ứng dụng React của chúng ta.
Điều đầu tiên chúng tôi muốn làm là tạo ra một mutation (thay đổi). Trong GraphQL, mutation tương ứng với các hoạt động PUT
, PUSH
và DELETE
của REST. Bởi vì chúng tôi chưa có bất kỳ dữ liệu nào trong database nên chúng tôi sẽ tạo một mutation để tạo một restaurant mới.
Để làm như vậy, chúng tôi sẽ nhập API
và graphqlOperation
từ AWS Amplify, xác định một mutation và sau đó xử lý mutation này.
Hãy xem một ứng dụng ví dụ khi thực hiện một mutation. Trong App.js
, trước tiên chúng tôi import React, CSS cho ứng dụng của chúng tôi và các thành phần AWS Amplify cần thiết.
import React, { Component } from 'react'; import './App.css'; import { withAuthenticator } from 'aws-amplify-react' import { API, graphqlOperation } from 'aws-amplify'
Tiếp theo, chúng tôi xác định một mutation để tạo mới một restaurant. Chúng tôi xác định rằng mutation nhận giá trị name và description và được đặt tên là createRestaurant
. Mutation này tự động được xác định khi chúng tôi tạo schema Restaurant
bên trên. Lưu ý rằng thay đổi được chỉ định trong GraphQL — một ngôn ngữ truy vấn domain-specific.
const CreateRestaurant = ` mutation($name: String!, $description: String) { createRestaurant(input: { name: $name description: $description }) { id name description } } `
Bây giờ, chúng tôi tạo thành component cho ứng dụng.
class App extends Component { //create initial state state = {name: '', description: ''} //update state when user types into inputs onChange = e => { this.setState({ [e.target.name]: e.target.value }) } //define function to execute mutation //render the component }
Tiếp theo, vẫn nằm trong component App
, chúng ta định nghĩa một hàm để xử lý mutation. Điều này xử lý các mutation bằng cách gọi API.graphql
, truyền đi mutation và data.
//define function to execute mutation createRestaurant = async() => { if (this.state.name === '' || this.state.description === '') return try { const restaurant = { name: this.state.name, description: this.state.description } await API.graphql(graphqlOperation(CreateRestaurant, restaurant)) this.setState({ name: '', description: '' }) console.log('restaurant successfully created!') } catch (err) { console.log('error creating restaurant...') } }
Sau đó, chúng ta tạo ra component, liên kết các hàm xử lý và các hàm mutation của chúng ta.
//render the component render() { return ( <div className="App"> <input value={this.state.name} onChange={this.onChange} name='name' /> <input value={this.state.description} onChange={this.onChange} name='description' /> <button onClick={this.createRestaurant}>Create Restaurant</button> </div> ) }
Sau cùng, chúng tôi export component cho App
, cùng với xác thực.
export default withAuthenticator(App, { includeGreetings: true });
Bạn sẽ có thể chạy code này và bắt đầu tạo các restaurant mới trong API.
Xem data source thực tế để xem liệu dữ liệu có ở đó không, hãy mở trang tổng quan AWS AppSync, chọn API của bạn, nhấp vào Data Sources trong menu bên trái, sau đó nhấp vào Resource Name. Thao tác này sẽ mở bảng Amazon DynamoDB. Trong bảng, bạn có thể xem dữ liệu trong tab Items.
Chạy truy vấn GraphQL
Tiếp theo, hãy xem làm sao để truy vấn dữ liệu từ API. Chúng tôi sẽ thực hiện theo 3 bước:
- xác định câu truy vấn
- thực hiện truy vấn khi ứng dụng tải
- lưu kết quả từ truy vấn ở state của chúng tôi và hiển thị kết quả đó trong UI
Trước tiên, hãy định nghĩa câu truy vấn trong một component mới. Lần nữa, chúng tôi đang sử dụng ngôn ngữ GraphQL để chỉ định truy vấn. Chúng tôi đang sử dụng truy vấn listRestaurants
đã được tự động xác định khi chúng tôi đẩy schema Restaurants
. Đoạn code dưới đây chỉ định rằng chúng tôi đang mong đợi một danh sách các item, mỗi item có id, name và description.
const ListRestaurants = ` query { listRestaurants { items { id name description } } }
Tiếp theo, chúng ta cần thêm một số trạng thái ban đầu bổ sung để giữ mảng (array) các restaurant được trả về từ server.
state = { name: '', description: '', restaurants: [] }
Chúng ta cũng sẽ cần thêm một sự kiện vòng đời componentDidMount
để truy vấn dữ liệu từ máy chủ GraphQL. Phương thức async này sẽ cập nhật state của component khi danh sách restaurant được trả về từ server.
async componentDidMount() { try { const restaurants = await API.graphql(graphqlOperation(ListRestaurants)) console.log('restaurants: ', restaurants) this.setState({ restaurants: restaurants.data.listRestaurants.items }) } catch (err) { console.log('error fetching data: ', err) } }
Cuối cùng, chúng ta sẽ tạo một component ánh xạ mảng (array) restaurants
từ state của component sang HTML.
{ this.state.restaurants.map((r, i) => ( <div key={i}> <p>{r.name}</p> <p>{r.description}</p> </div> )) }
Bây giờ, khi chúng tôi chạy ứng dụng, sẽ thấy rằng dữ liệu từ API đang được hiển thị trong danh sách trên màn hình. Tuy nhiên, ứng dụng sẽ không hiển thị bất kỳ thay đổi nào khi dữ liệu được cập nhật — ví dụ: khi bạn thêm restaurant mới.
Vì vậy cho người mới bắt đầu, hãy cập nhật phương thức createRestaurant
để cung cấp phản hồi tích cực cho UI. Ngay bây giờ, khi chúng ta tạo một item mới, database được cập nhật, nhưng giao diện người dùng chưa biết về item mới. Để giải quyết việc này, chúng tôi sẽ cập nhật mảng restaurant trong phương thức createRestaurant
bằng cách thêm mục mới vào mảng:
createRestaurant = async() => { if (this.state.name === '' || this.state.description === '') return try { const restaurant = { name: this.state.name, description: this.state.description } const restaurants = [...this.state.restaurants, restaurant] this.setState({ name: '', description: '', restaurants }) await API.graphql(graphqlOperation(CreateRestaurant, restaurant)) console.log('restaurant successfully created!') } catch (err) { console.log('error creating restaurant...') } }
Đăng ký dữ liệu theo thời gian thực
Tiếp theo, chúng ta muốn có thể làm việc với dữ liệu thời gian thực. Trong GraphQL, subscription (đăng ký) cho phép bạn lấy dữ liệu theo thời gian thực. Khi có dữ liệu mới, subscription được kích hoạt và dữ liệu mới được truyền xuống thông qua subscription. Chúng ta tuỳ ý xử lý dữ liệu mới này.
Trong ứng dụng của chúng tôi, chúng tôi sẽ đăng ký với một loạt restaurant và chúng tôi sẽ tạo subscription onCreateRestaurant
để kích hoạt bất kỳ lúc nào khi một restaurant mới được tạo ra. Sau đó chúng tôi sẽ lấy item mới từ subscription, cập nhật mảng hiện có của chúng tôi và gọi setState
để hiển thị lại UI cùng dữ liệu mới.
Cũng như đối với các thay đổi và truy vấn, chúng tôi bắt đầu bằng cách xác định subscription bằng GraphQL domain-specific language.
// define the subscription const OnCreateRestaurant = ` subscription { onCreateRestaurant { id name description } } `
Subscription sẽ được tạo ra trong phương thức vòng đời componentDidMount
trước hoặc sau truy vấn GraphQL mà chúng ta đã thiết lập:
async componentDidMount() { try { const restaurants = await API.graphql(graphqlOperation(ListRestaurants)) console.log('restaurants: ', restaurants) this.setState({ restaurants: restaurants.data.listRestaurants.items }) } catch (err) { console.log('error fetching data: ', err) } API.graphql(graphqlOperation(OnCreateRestaurant)) .subscribe({ next: eventData => { const data = eventData.value.data.onCreateRestaurant console.log('data: ', data) const restaurants = [ ...this.state.restaurants.filter(r => r.name !== data.name && r.description !== data.description), data ] this.setState({ restaurants }) } }) }
Bây giờ, nếu bạn mở hai cửa sổ trình duyệt, bạn sẽ có thể tạo thay đổi trong một màn hình và nhìn thấy cập nhật diễn ra trên tất cả các màn hình khác.
Nếu bạn nhìn vào phương thức .filter
mà chúng tôi đã sử dụng trong việc tạo mảng các restaurant mới trong subscription, bạn có thể thấy chúng tôi đang kiểm tra liệu có các trùng lắp có cùng tên và mô tả hay không. Có lẽ cách tốt hơn để làm điều này trong thực tế sẽ là tạo một ID duy nhất của khách hàng, ID này cũng được lưu trữ trong database và filter dựa trên identifier đó.
Tạo một REST API với AWS Lambda
GraphQL là một công nghệ tiên tiến tuyệt vời, nhưng đôi khi dự án của chúng tôi sẽ yêu cầu tạo ra một REST API truyền thống. Với AWS Lambda và Amplify, việc tạo các serverless REST API bằng cách sử dụng CLI cũng rất dễ dàng.
Khi chúng ta tạo ra GraphQL API, chúng ta đã dùng lệnh amplify create api
. Lệnh này cho chúng ta tùy chọn tạo một GraphQL API hoặc một API REST. REST API có thể được cấu hình để sử dụng chức năng độc lập serverless Express hoặc chức năng serverless JavaScript được cấu hình sẵn để làm việc với các hoạt động CRUD của Amazon DynamoDB.
Tùy chọn chúng tôi sẽ sử dụng cho API này là chức năng serverless Express.
Hãy tiếp tục và bổ sung tính năng mới:
amplify add api
Như thường lệ, điều này sẽ nhắc bạn điền vào một số chi tiết cấu hình. Cung cấp các tùy chọn sau:
- service type: REST
- nhập tên tài nguyên sẽ được sử dụng trong dự án: ví dụ: amplifyrestapi
- enter a path for the REST endpoints: e.g. /people (nhập đường dẫn cho REST endpoint)
- Lambda source: Create a new Lambda function (tạo hàm mới Lambda)
- AWS Lambda function name: amplifyrestapifunction (đặt tên cho hàm Lambda)
- function template: Serverless express function (Integration with Amazon API Gateway)
- edit the local lambda function now? Y (chỉnh sửa hàm Lambda cục bộ)
Now, you will be able to edit the lambda function locally. In the file, we'll replace the existing app.get('/people')
method with the following: (Chỉnh sửa hàm Lambda để thay thế phương thức app.get('/people'))
// amplify-web-app/amplify/backend/function/amplifyrestapi/src/app.js app.get('/people', function(req, res) { const people = [ { name: "Nader" }, { name: "Amanda" }, { name: "Chris" }, { name: "" } ] res.json({ success: true, people }) });
This just returns a constant list of names for demo purposes. Save this file, and continue with the following answers: (kết quả trả về danh sách tên dùng cho mục đích demo)
- restrict API access? Yes (hạn chế quyền truy cập)
- who should have access? Authenticated users only (Chỉ có người dùng đã xác thực có quyền truy cập)
- what kind of access do you want for Authenticated users? read (kiểu truy cập nào dùng cho người dùng đã xác thực - đọc)
- add another path? N (Bổ sung path khác)
Việc này đã tạo ra một hàm Lambda mới cục bộ mà chúng ta có thể update và push vào tài khoản của mình khi cần thiết. Code cho hàm lambda này được đặt tại amplify/backend/function/amplifyrestapi/src.
Bây giờ, hãy push các cập nhật vào tài khoản của chúng tôi:
amplify push
Truy vấn REST API từ client (máy khách)
Bây giờ, hàm Lambda của chúng ta đã được thiết lập và đang chạy, và chúng ta có thể bắt đầu tương tác với nó!
Trước tiên, hãy truy vấn dữ liệu từ API mới và hiển thị nó trong UI của chúng tôi. Để làm như vậy, chúng tôi sẽ sử dụng class API từ Amplify, gọi API.get
. Trong phần trước, chúng tôi đã sử dụng API.graphql
để gửi các yêu cầu cho GraphQL API của chúng tôi, nhưng có nhiều phương thức có sẵn trong class API. Bạn có thể tìm hiểu thêm về lớp API trong tài liệu chính thức.
import { API } from 'aws-amplify' // 1. in the initial state, create an empty array of people state = { people: [] } // 2. in componentDidMount, we will fetch this data using the API class try { const peopleData = await API.get('amplifyrestapi', '/people') this.setState({ people: peopleData.people }) } catch (err) { console.log('error fetching from Lambda API') } // 3. render the people data to the UI in the render method { this.state.people.map((person, index) => ( <p key={index}>{person.name}</p> )) }
Bây giờ, chúng ta sẽ có thể chạy ứng dụng, tìm nạp dữ liệu mọi người từ API của chúng tôi và hiển thị nó trên màn hình.
Cập nhật hàm lambda từ CLI
Ngoài việc tạo ra một hàm Lambda mới, chúng ta cũng có thể cập nhật hàm Lambda của chúng ta từ CLI.
Hãy thay đổi hàm để truy cập API và lấy dữ liệu thay vì dùng constant (hằng số) cố định. Để làm như vậy, chúng tôi sẽ sử dụng thư viện axios để tạo các yêu cầu HTTP và chúng tôi sẽ lấy dữ liệu từ Star Wars API.
Để sử dụng axios, chúng ta cần đi đến amplify/backend/function/amplifyrestapi/src và cài đặt nó ở đó. Axios được cài đặt trong thư mục dự án của hàm lambda, không phải thư mục chính app, bởi vì nó sẽ chạy hàm Lambda từ phía máy chủ.
yarn add axios # or npm install axios
Bây giờ, axios được cài đặt, chúng tôi sẽ cập nhật hàm Lambda để lấy dữ liệu từ Star Wars API:
var axios = require('axios') app.get('/people', function(req, res) { axios.get('https://swapi.co/api/people/') .then(response => { res.json({ success: true, people: response.data.results }) }) .catch(error => { res.json({ success: false, error }) }) });
Bây giờ, lưu file lại và chạy amplify push
từ thư mục chính của dự án để cập nhật hàm Lambda của bạn trên cloud.
amplify push
Bây giờ, API của chúng tôi đã được cập nhật và sẵn sàng hoạt động!
Khi chúng tôi tải lại ứng dụng, bây giờ chúng ta sẽ thấy dữ liệu được trả về từ Star Wars API.
Tổng kết
Trong loạt bài này, bạn đã học cách bắt đầu với AWS Amplify và thêm nó vào dự án React của bạn, cũng như cách thêm authentication (xác thực), storage (lưu trữ), hosting và GraphQL hoặc REST API — tất cả không cần code hoặc cung cấp máy chủ theo cách thủ công . Đó là sức mạnh rất lớn cho các nhà phát triển.
Tôi hy vọng những bài viết này đã truyền cảm hứng cho bạn để xây dựng các ứng dụng web serverless của riêng bạn thông qua công nghệ serverless và AWS Amplify! Hãy cho chúng tôi biết suy nghĩ của bạn trong phần bình luận bên dưới.
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.
Update me weekly