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:

  • How to create the app with login
  • How to add a database and work with the data
  • How to add file storage and use those files
  • How to allow users to upload their own files and data

If you want to read this article offline then you can download it here.

How to Create the App with Signup, Login and Logout

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.

How to Build the React App

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.

How to Add a Database to our App

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

How to Build a Full Stack App with AWS Amplify and React
4.75 GEEK