AWS Amplify is a tool developed by Amazon Web Services that helps make app development easier.
It includes loads of features which allow you to quickly and easily work with other AWS services. This means you can spend more time building the features that make your app unique.
This tutorial is split into four parts:
If you want to read this article offline then you can download it here.
In this first section we’ll be setting up a new React App with AWS Amplify to add Sign up, Login and Logout in the easiest way possible.
We need to start by creating a new React app using create-react-app
. Open a terminal and run these commands. If you don’t have create-react app installed then you can run npm i -g create-react-app
first.
npx create-react-app amplify-react-app
cd amplify-react-app
With that set up we can now install Amplify and then configure it.
npm install -g @aws-amplify/cli
amplify configure
This will open up an AWS console tab in your browser. Make sure that you’re logged into the correct account with a user that has admin permissions.
Go back to the terminal and follow the steps, adding a region and name for the user. This will then take you back the the browser where you can follow the steps to create the new user. Make sure to stay on the page where you see the key and secret!
Back in the terminal again you can follow the steps, copying the access key and secret into the terminal when asked. When you are asked if you want to add this to a profile say Yes
. Create a profile that is something like serverless-amplify
.
Now we can initialise the amplify setup by running amplify init
. You can give the project a name and answer all the questions. Most of them should be correct already. This then takes a while to make the changes on your account.
Once done we need to add authentication to the app. We do this with amplify add auth
. Select the method as default
the sign in to email
and then no, I am done
. We can now deploy this by running amplify push
. This takes a while but at the end, our src/aws-exports.js
file has been created.
Now we can get onto creating the react app. Start by installing the Amplify npm packages we need.
npm install --save aws-amplify @aws-amplify/ui-react
Now we can start editing the code of our app. In our src/App.js
file we can remove everything in the headers and replace it with this:
<header className="App-header">
<AmplifySignOut />
<h2>My App Content</h2>
</header>
This is a very basic set up but you could put the main content of your site here and put the AmplifySignOut
button where ever you want it to be.
We also need to add some extra imports to the top of the file:
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
import { AmplifySignOut, withAuthenticator } from '@aws-amplify/ui-react';
Amplify.configure(awsconfig);
Now the last thing that we need to do is to change the way that we export the app. Change the last line to be export default withAuthenticator(App);
to add Amplify to this app.
Now when we run npm start
we should get a login screen. We’ve not created this so it has come from Amplify itself.
If we try and log in then it will fail, as we need to sign up first. We can click create account
and then enter our email and a password to sign up.
Once we’ve confirmed our email by submitting the code we were sent, we get onto the home page of our app. If we log out we can now log back in as expected.
If you want to add data to your React app but don’t want to have to build an API, then this is the section for you. We’ll be having a look at how we can use AWS amplify inside our React app to allow us to access our database on the back end using GraphQL.
To start we need to go into the terminal and run:
amplify add api
This will start us in a set of CLI options, asking us a few configuration questions:
What kind of API we want to use: GraphQL
The name of the API: songAPI
How we want to authenticate the API: Amazon Cognito User Pool
Advanced Settings: No, I am done
Do you have a schema: No
What kind of schema do you want: Single object with fields
After a little setup we are asked if we want to edit our new schema. We want to say yes. This opens the GraphQL schema which we’re going to update to be the schema listed here.
type Song @model {
id: ID!
title: String!
description: String!
filePath: String!
likes: Int!
owner: String!
}
With our schema set up we’re going to run amplify push
which will compare our current amplify setup with that on our AWS account. As we’ve added a new API we’ll have changes, so we will be asked if we want to continue with the changes.
Once we’ve selected Yes then we’re put into another set of options.
Do we want to generate code for our GraphQL API: Yes
Which Language: JavaScript
File pattern for the new files: src/graphql//*.js**
Generate all operations: Yes
Maximum statement depth: 2
This will now deploy all of the changes to AWS and also set up the new request files in our React app. This does take a few minutes to do.
Once that is completed we can go into our App.js
file and rename it to be App.jsx
. This just makes it easier to write our JSX code.
We now need to write a function in here to get the list of songs from our new database. This function calls the GraphQL API passing in the operation of listSongs
. We also need to add a new state to the App
component.
const [songs, setSongs] = useState([]);
const fetchSongs = async () => {
try {
const songData = await API.graphql(graphqlOperation(listSongs));
const songList = songData.data.listSongs.items;
console.log('song list', songList);
setSongs(songList);
} catch (error) {
console.log('error on fetching songs', error);
}
};
We now need to add or update a few imports to our file to get this working:
import React, { useState, useEffect } from 'react';
import { listSongs } from './graphql/queries';
import Amplify, { API, graphqlOperation } from 'aws-amplify';
The listSongs
is one of those functions created by amplify to help us access our data. You can see the other functions that are available in the ./graphql
folder.
Now we want this function to be called once when the component renders, but not every time that it re-renders. To do this we use useEffect
but make sure to add a second parameter of []
so that it only gets triggered once.
useEffect(() => {
fetchSongs();
}, []);
If we now start our app using npm start
and then go to the app we can open the console and see a log of song list []
. This means that the useEffect
has called the fetchSongs
which is console logging out the result, but currently there is nothing in the database.
To correct this we need to log into our AWS account and add the DynamoDB service. We should find a new table called something like Song-5gq8g8wh64w-dev
. If you can’t find it make sure to check other regions as well.
This currently has no data so we need to add some. For now we’re going with manually creating new data in here. Under Items
click Create item
and then make sure the dropdown in the top left shows text
. If it shows tree
then just click it and change it to text
. We can then make the data go into that row.
We start with the GraphQL schema, giving the row some data for each attribute. But we also need to add createdAt
and updatedAt
values. You can find this using the browser console.
Type new Date().toISOString()
and copy the result of that. You should end up with an object like this:
{
"id": "gr4334t4tog345ht35",
"title": "My First Song",
"description": "A test song for our amplify app",
"owner": "Sam Williams",
"filePath": "",
"likes": 4,
"createdAt": "2020-08-13T07:01:39.176Z",
"updatedAt": "2020-08-13T07:01:39.176Z"
}
If we save that new object then we can go back into our app and refresh the page. We should now be able to see our data in the console.log.
We can now use this data in our app to show the list of songs that we just got. Replace the existing text of song list
with this set of JSX.
<div className="songList">
{songs.map((song, idx) => {
return (
<Paper variant="outlined" elevation={2} key={`song${idx}`}>
<div className="songCard">
<IconButton aria-label="play">
<PlayArrowIcon />
</IconButton>
<div>
<div className="songTitle">{song.title}</div>
<div className="songOwner">{song.owner}</div>
</div>
<div>
<IconButton aria-label="like">
<FavoriteIcon />
</IconButton>
{song.likes}
</div>
<div className="songDescription">{song.description}</div>
</div>
</Paper>
);
})}
</div>
This code is mapping over each song in the list and rendering a new Paper
for them with all the details we need.
We’re using the MaterialUI library to help make this look nice for us so we need to make sure to run npm install --save @material-ui/core @material-ui/icons
to install those packages and then add them to the imports at the top of the file too:
import { Paper, IconButton } from '@material-ui/core';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import FavoriteIcon from '@material-ui/icons/Favorite';
With this, if we save and reload our app we now get this:
Whilst this is ok, we can update the CSS to make it look far better. Open up your App.css
file and change it to this:
.App {
text-align: center;
}
.App-logo {
height: 10vmin;
pointer-events: none;
}
.App-header {
background-color: #282c34;
min-height: 5vh;
display: flex;
align-items: center;
justify-content: space-around;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
.songList {
display: flex;
flex-direction: column;
}
.songCard {
display: flex;
justify-content: space-around;
padding: 5px;
}
.songTitle {
font-weight: bold;
}
#react #aws #cloud #web-development #developer