To get started, we will first create a new React application using the Create React App CLI.
If you do not already have Creeate React App installed, install it now with the following command:
npm install -g create-react-app
create-react-app react-aws-app
First, change into the new directory of the app we just created.
cd react-aws-app
Next, run the following command to launch the app in the web browser:
npm start
Installing & configuring a new mobile hub project.
npm i -g awsmobile-cli
awsmobile configure
If you need to get an accessKeyId & secretAccessKey:
- Visit the IAM Console.
- Click Users in left hand menu.
- Click Add User.
- Give the user a name & choose programatic access as the access type & click next.
- Click Create Group.
- Give the group a name & choose Administrator Access as the access type & click Create Group.
- Click Next & click Create User.
- Copy the accessKeyId & secretAccessKey to the terminal to configure the CLI.
awsmobile init
After running the above command you will have a few options:
- Choose default for source directory
- Choose default for project's distribution directory
- Choose default for build command
- Choose default for project's start command
- Give the project a name of AmplifyReact
Now that the project is successfully created, we can view it in the AWS Console by running the following command:
awsmobile console
In this section, we'll first integrate our AWS Mobile Hub project in with our newly created React application using the AWS Amplify library.
We'll also learn how to add a new service, Amazon Cognito, to our existing AWS Mobile Hub project using the CLI. Finally, we'll implement Authentication into the application using Amazon Cognito with AWS Amplify.
- Open src/index.js
- Add the following code below the last
import
statement
// src/index.js
import Amplify from 'aws-amplify'
import config from './aws-exports'
Amplify.configure(config)
- Add the new User Signin functionality using the CLI
awsmobile user-signin enable
- Push the new configuration to the Mobile Hub Console
awsmobile push
- To view the console, run the following command:
awsmobile console
Now, in the list of Backend services, we see that User Signin is now enabled.
-
Open src/App.js
-
Import the
withAuthenticator
HOC fromaws-amplify-react
// src/App.js
import { withAuthenticator } from 'aws-amplify-react'
- Wrap the App export with the
withAuthenticator
HOC
export default withAuthenticator(App)
AWS Amplify Auth category has over 30 different methods available, including signUp
, confirmSignUp
, signIn
, confirmSignIn
, changePassword
, forgotPassword
& many many others. You can view the entire API here.
To manually sign up a new User with our existing Amazon Cognito configuration, we can call Auth.signUp
, & must provide the following parameters:
- username
<string>
- password
<string>
- attributes
<object>
- email
<string>
- phone_number
<string>
- email
We would call some method, passing in the above info to Auth.signUp
. In React, it could look something like this:
import { Auth } from 'aws-amplify'
signUpUser = () => {
const { username, password, email, phone_number } = this.state
Auth.signUp({
username, password, attributes: { email, phone_number }
})
.then(success => console.log('successfully signed up user!: ', success))
.catch(err => console.log('error signing up user: ', err))
}
This Sign Up would trigger an MFA using the provided phone number.
To handle MFA on user sign up & sign in, we can use confirmSignUp
& confirmSignIn
.
To see how to build a custom UI using the Auth class, check out this section of the documentation.
In this section, we'll see how to add a new Lambda function to our application. We'll then learn how to make changes to the Lambda function & push the new changes to our Mobile Hub console.
- Run the following command to create a new Lambda function:
awsmobile cloud-api enable -p
- Choose the following options:
- Create a new API
- API name: PetAPI
- HTTP path name: /pets
- Here, choose default Lambda function name by hitting enter on your keyboard
- Add another HTTP path: n
- In src/App.js, add the following below the last import
// src/App.js
import { API } from 'aws-amplify'
let apiName = 'PetAPI';
let path = '/pets';
- In the App component add a new
componentDidMount
lifecycle method to log out the returned data from the API.
async componentDidMount() {
const data = await API.get(apiName, path)
console.log('data: ', data)
}
Now, we should be able to run the app and see some information passed back to us from the API.
To see what is going on here, open the following file: awsmobilejs/backend/cloud-api/PetAPI/app.js
Here, we can see that the Lamdba function is running an express server, handling various paths. If we look at the app.get('/pets/'
path, we see that for right now it is returning res.json(req.apiGateway.event);
Let's update this to return an array of pets.
- Update the
app.get('/pets/'
path to the following:
app.get('/pets', function(req, res) {
const pets = [
'Buster', 'Mary', 'Spike', 'Pebbles'
]
res.json({
data: pets
});
});
- Push the new code to Mobile Hub:
awsmobile push
- Rerun the app
npm start
Next, we want to render the data being returned from the API. To do so, we'll create some state in the component to hold the data. Then, once the data is returned from the API, we'll reset the state, passing in the new data.
- Create state in the component
state = {
pets: []
}
- Change
componentDidMount
to set the state when the data is returned.
async componentDidMount() {
const data = await API.get(apiName, path)
console.log('data: ', data)
this.setState({
pets: data.data
})
}
- Finally, add the following code to your render method to display the list of pets in the UI:
{
this.state.pets.map((pet, index) => (
<h2 key={index}>{pet}</h2>
))
}
π€ Lesson 4 - Adding Analytics with Amazon Pinpoint
Next, we'd like to add analytics to the app!
When we created the new Mobile Hub project, the initial configuration has Pinpoint enabled by default so we do not need to do anything add the service, we can just start using it.
The will be using the Analytics
API from AWS Amplify to interact with Pinpoint & to log analytics.
Analytics can take the following arguments:
// 1. only the event name
Analytics.record({ name: 'Add to cart button clicked' })
// 2. event name & some attributes
Analytics.record({ name: 'Added socks to shopping cart', attributes: { username: 'amanda33' }})
// 3. event name, attributes, & metrics
Analytics.record({ name: 'Added socks to shopping cart', attributes: { username: 'amanda33' }, metrics: { time: '8:33pm ET' } })
Let's create a button that records an event.
In src/App.js, import the Analytics
module:
// src/App.js
import { Analytics } from 'aws-amplify'
Next, add the following method to the class:
addToCart = () => {
console.log('Simulating adding item to cart.')
Analytics.record('Item added to cart!')
}
Now, create a button in the render method & attach the method to the onClick function of the button:
<button onClick={this.addToCart}>Add To Cart</button>
Now, click on the button a couple of times. We should now be able to see the data from this event logged into our Pinpoint console.
Next, let's view the Pinpoint console to see the events we've logged so far.
- Open the AWS Mobile Hub console
awsmobile console
-
Click Analytics in the top right hand corner
-
Click on Events in the left menu
Next, we would like to add a AWS AppSync GraphQL API to the application.
We can create the new API from the command line:
awsmobile appsync enable -p
Next, choose API_KEY as the auth type.
Now, push the new configuration to AWS Mobile Hub:
awsmobile push
Now that the API has been created, let's go into the AWS console to update the configuration.
Visit the AWS AppSync console at https://console.aws.amazon.com/appsync/.
Fromt here, click on the AmplifyReact API to open it in the console.
Now we need to update the existing schema to our new schema.
Click on Schema in the left hand menu to open the schema editor.
Here, delete the existing schema and add the following, then click Save Schema:
type Pet {
id: ID!
name: String!
}
type Query {
fetchPet(id: ID!): Pet
}
Next, click on the Create Resources button in the top right corner.
When asked to Define or select a type, choose Use existing type, and then choose the Pet type. Then scroll down & click Create.
Once the resources have finished being created, we can start executing mutations against the API.
In the left hand menu, click on Queries, & add the following mutation into the query editor, then click the orange play button:
mutation create {
createPet(input:{
name: "Spike"
}) {
id
}
}
Feel free to create as many Pets as you would like, as we will be querying for this data in just a moment.
If you would like to query the data to make sure everything is working properly, try using this query in the query editor:
query list {
listPets {
items {
id
name
}
}
}
Now that the API is created & working properly, let's go ahead and query for data from the client & show it in the UI.
In src/App.js, let's go ahead and import API & graphqlOperation from 'aws-amplify':
// src/App.js
import { API, graphqlOperation } from 'aws-amplify'
Next, we'll define our query:
const ListPets = `
query {
listPets {
items {
id
name
}
}
}
`
Now, in the class, we'll define some state, and set a pets property equal to an empty array for now:
state = { pets: [] }
Now that we have some initial state, we'll call the AppSync API to fetch the data within the componentDidMount
lifecycle hook:
async componentDidMount() {
const pets = await API.graphql(graphqlOperation(ListPets))
console.log('pets: ', pets) // optional, if you would like to view the shape of the data
this.setState({ pets: pets.data.listPets.items })
}
In the render method, we can now display the data to the UI:
{
this.state.pets.map((pet, index) => (
<h2 key={index}>{pet.name}</h2>
))
}
The final component code for querying the AWS AppSync API should look like this:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import { API, graphqlOperation } from 'aws-amplify'
const ListPets = `
query {
listPets {
items {
id
name
}
}
}
`
class App extends Component {
state = { pets: [] }
async componentDidMount() {
const pets = await API.graphql(graphqlOperation(ListPets))
console.log('pets: ', pets)
this.setState({ pets: pets.data.listPets.items })
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
{
this.state.pets.map((pet, index) => (
<h2 key={index}>{pet.name}</h2>
))
}
</div>
);
}
}
export default App;
First, we need to create a mutation:
const CreatePet = `
mutation($name: String!) {
createPet(input: {
name: $name
}) {
id
}
}
`
Now we need to store some state in the class to keep up with user input:
state = { name: '', pets: [] }
Next, we'll create an onChange
class method that will handle user input, storing it in the state:
onChange = (e) => { this.setState({ name: e.target.value }) }
Now, we'll create a class method that will call the API to create the mutation:
createPet = () => {
const pet = { name: this.state.name }
API.graphql(graphqlOperation(CreatePet, pet))
const pets = [...this.state.pets, pet]
this.setState({ pets, name: '' })
}
Finally, in the render method we'll create a button & input form to work with the new methods:
<input onChange={this.onChange} placeholder='Pet name' />
<button onClick={this.createPet}>Create Pet</button>
Throughout this tutorial, we've created a few resources in your AWS account. If you are interested in removing any resources you will not be using in the future, here are the resources you should delete around this project:
- In Mobile hub, delete the new project we created here
- In Amazon s3, delete the bucket associated with this project
- In AWS AppSync, delete the API we created along with this project