Building Serverless Web Applications with React & AWS Amplify
Tags: aws, javascript, beginners, webdev
Published: 2022-10-10 02:43:53


React makes it intuitive to build **real-world** web applications. But in reality, you need to use a host of other **services **to get the app in front of real users.

This course walks you through setup and implementation to get your cloud-based application up and running.

You’ll learn to set up:

- Install and configure **AWS Amplify** into your React applications
- Add services like Authentication, *APIs *using *GraphQL*, interact and deploy Serverless functions, and store data in *Amazon S3*.
- Deploy your React application and make it available to all your users.
 

# Part 1

## Install & Configure the AWS Amplify CLI

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here or in the video that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 
**[🤔 You can setup your project with a guided help from the Official AWS documentation here](https://docs.amplify.aws/start)**

## Prerequisites

- [Node.js](https://nodejs.org/) v10.x or later
- [npm](https://www.npmjs.com/) v5.x or later
- [git](https://git-scm.com/) v2.4.1 or later

- This tutorial assumes you are familiar with both JavaScript/ES6 and React. If you need to refresh some of the core concepts, we recommend you go through [the React official tutorial](https://reactjs.org/tutorial/tutorial.html)

- Also make sure you have an AWS account. You need one in order to follow all the steps. You can create an AWS account [here](https://portal.aws.amazon.com/billing/signup?redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation#/start)

- 🤔 for the next steps, you have also this other video resource and follow the steps: https://www.youtube.com/watch?v=fWbM5DLh25U

- Install the CLI

```bash
npm install -g @aws-amplify/cli
```

- Configure the CLI with the user from your AWS account

```bash
amplify configure
```

- This command should open the AWS console. Log in with your account and jump back to the command line
- Specify the AWS reagion closer to you or the one you prefer
- Set the username of the user that we are about to create

```bash
Specify the AWS Region
? region:  # Your preferred region
Specify the username of the new IAM user:
? user name:  # User name for Amplify IAM user
Complete the user creation using the AWS console
```

- This should open the IAM dashboard in our AWS account with pre-configured settings that we can accept by clicking next in all the steps:
  - `Next: Permissions`
  - `Next: Review`
  - and finally `Create User`

> 🤔 Amazon IAM (Identity and Access Management) enables you to manage users and user permissions in AWS. You can learn more about Amazon IAM [here](https://aws.amazon.com/iam/).

- Now you will see the user created, with an `Access key ID` and a `Secret access key` which you need to paste in your command line
- Now you need to set a Profile Name (choose the name of your choice)
- and that's it!, you have the AWS Amplify CLI setup and ready to create new projects!

# Part 2

## Create & Configure an AWS Amplify Project with a React Application

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here or in the video that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 

- create a Create-React-App using `npx` and run inside the app `amplify init`

```bash
npx create-react-app <YOUR-APP-NAME> # YOUR-APP-NAME can be any name
cd <YOUR-APP-NAME>
```

- Fron the root of your project, run:

```bash
amplify init
```

You will be prompted for some information about the app:

```bash
Enter a name for the project (<YOUR-APP-NAME>)

# All AWS services you provision for your app are grouped into an "environment"
# A common naming convention is dev, staging, and production
Enter a name for the environment (dev)

# Sometimes the CLI will prompt you to edit a file, it will use this editor to open those files.
Choose your default editor

# Amplify supports JavaScript (Web & React Native), iOS, and Android apps
Choose the type of app that you're building (javascript)

What JavaScript framework are you using (react)

Source directory path (src)

Distribution directory path (public)

Build command (yarn run-script build)

Start command (yarn run-script start)

# This is the profile you created with the `amplify configure` command in the introduction step.
Do you want to use an AWS profile
```

> ❗ The default build folder for a Create React App application is `public` and not `build`

- the Amplify CLI will infer as much information as it can from the current project setup.
- A few things happen with this process:

  - a directory called `amplify` at the top level of the app, that stores your backend definition
  - a file called `aws-exports` in the `src` directory that holds all the configuration for the services you create and will create with AWS Amplify
  - it modifies the `.gitignore` file adding some generated files to the ignore list
  - A cloud project is created in your AWS Amplify console

- now let's install the react-amplify libraries needed

```bash
npm install aws-amplify @aws-amplify/ui-react
# or
yarn add aws-amplify @aws-amplify/ui-react
```

> ❗ the React Library has a new package name! (@aws-amplify/ui-react)

- Now we are ready to add new features to our React app!

# Part 3

## Use the AWS Amplify withAuthenticator HOC to Implement a React User Authorization Flow

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here  that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 

- the Amplify CLI comes with commands to help you create and add services to your applications
- in this lesson, you will add authentication service to your app

- First, in the root of your project, you run:

```bask
amplify add auth

? Do you want to use the default authentication and security configuration? Default configuration
? How do you want users to be able to sign in? Username
? Do you want to configure advanced settings?  No, I am done.
```

- In order to deploy the service, you can run:

```bash
amplify push
```

- this will show you the operation it will execute. This process may take a while depending on the service you are pushing (First time always takes a little more)

```bash
$ amplify push
✔ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name       | Operation | Provider plugin   |
| -------- | ------------------- | --------- | ----------------- |
| Auth     | <__RESOURCE_NAME__> | Create    | awscloudformation |
? Are you sure you want to continue? Yes
```

- after the process is finished, we can now setup and configure our React app with the new AWS resource.

- open `src/index.js` and include the next lines of code:

```javascript
import Amplify from "aws-amplify"
import awsExports from "./aws-exports"
Amplify.configure(awsExports)
```

> 👍 The `aws-exports.js` file is auto-generated, so you should not edit this file during this steps ( ...or any really XD )

- Now we can go to `src/App.js` to secure our app with our Auth service:

```javascript
// 1. import the `withAuthenticator` component
import { withAuthenticator } from "@aws-amplify/ui-react"

// 2. Change the default export with a `withAuthenticator` call passing the main component
export default withAuthenticator(App)
```

- Now we can run our app again and see the new Authentication flow that protects our whole app

```bash
yarn start
# or
npm start
```

- You should be able to see the app loads with an authentication flow in place (auth form)
- If you create a user and log in, even if you refresh the page you will be still logged in, that's because your user sessions is stored in localStorage by the Library itself.
- you are using the default React UI library for the form component, but you can customize it the way you prefer
  - Customize the look and feel
  - Add/Remove fields
  - and also other configurations
- You have access to the `Auth` class too, which lets you create your own custom Auth flow
- `Auth` has over 30 methods including `signUp`, `signIn`, `forgotPassword` and `signOut`, that gives you full control over all the Authentication flow.

> ❗ To include a sign out button, you need to follow other steps rather than adding a second parameter to the `withAuthenticator` High-order component (HoC). You can follo the new steps [here](https://docs.amplify.aws/lib/auth/getting-started/q/platform/js#option-2-call-authentication-apis-manually)
 

# Part 4

## Manually Sign Up New Users in React with AWS Amplify Auth Class

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 

> ❗ This lesson is using React Class Components. you are free to use the Class syntax or change to use Function components, the core Auth methods will work in both escenarios with a slight different Syntax

- Even you use Class components or function components, here are the `Auth` methods you need to perform **Sign up, Sign in and Sign out** operations
- Styling is something you can tweak to match your overall app design, there is no restrictions around this impose by the Amplify framework

## Sign up

```javascript
import { Auth } from "aws-amplify"

async function signUp() {
  try {
    const { user } = await Auth.signUp({
      username,
      password,
      attributes: {
        email, // optional
        phone_number, // optional - E.164 number convention
        // other custom attributes
      },
    })
    console.log(user)
  } catch (error) {
    console.log("error signing up:", error)
  }
}
```

the `Auth.signUp` method returns a Promise with a data object of type `[ISignUpResult](https://github.com/aws-amplify/amplify-js/blob/4644b4322ee260165dd756ca9faeb235445000e3/packages/amazon-cognito-identity-js/index.d.ts#L136-L139)` with a `[CognitoUser](https://github.com/aws-amplify/amplify-js/blob/4644b4322ee260165dd756ca9faeb235445000e3/packages/amazon-cognito-identity-js/index.d.ts#L48)`

```javascript
{
  user: CognitoUser
  userConfirmed: boolean
  userSub: string
}
```

## Confirm Sign up

- this is required if you enabled multi-factor auth

```javascript
import { Auth } from "aws-amplify"

async function confirmSignUp() {
  try {
    await Auth.confirmSignUp(username, code)
  } catch (error) {
    console.log("error confirming sign up", error)
  }
}
```

- You can also pass **custom attributes** during the signup process like so:

```javascript
Auth.signUp({
  username,
  password,
  attributes: {
    email,
    "custom:favorite_flavor": "Cookie Dough", // custom attribute, not standard
  },
})
```

From the Official docs:

> Amazon Cognito does not dynamically create custom attributes on sign up. In order to use a custom attribute, the attribute must be first created in the user pool. To open the User Pool to create custom attributes using the Amplify ClI, run amplify console auth. If you are not using the Amplify CLI, you can view the user pool by visiting the AWS console and opening the Amazon Cognito dashboard.

## Sign in

```javascript
import { Auth } from "aws-amplify"

async function signIn() {
  try {
    const user = await Auth.signIn(username, password)
  } catch (error) {
    console.log("error signing in", error)
  }
}
```

### Re-send confirmation code

```javascript
import { Auth } from "aws-amplify"

async function resendConfirmationCode() {
  try {
    await Auth.resendSignUp(username)
    console.log("code resent successfully")
  } catch (err) {
    console.log("error resending code: ", err)
  }
}
```

## Sign out

```javascript
import { Auth } from "aws-amplify"

async function signOut() {
  try {
    await Auth.signOut()
  } catch (error) {
    console.log("error signing out: ", error)
  }
}
```

- You can even execute a [Global sign-out](https://docs.amplify.aws/lib/auth/emailpassword/q/platform/js#global-sign-out) to sign out the user from all its devices

```javascript
import { Auth } from "aws-amplify"

async function signOut() {
  try {
    await Auth.signOut({ global: true }) // this is the main difference
  } catch (error) {
    console.log("error signing out: ", error)
  }
}
```
 # Part 5

## Create & Interact with an AWS AppSync GraphQL API with AWS Amplify

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here   that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 

## AWS Amplify !== AWS AppSync

[Appsync](https://aws.amazon.com/appsync/) is the AWS service focus on creating flexible APIs, and Amplify is the framework that combines multiple AWS tools to help you build any type of Application.

## Create a GraphQL API

```bash
amplify add api
```

Select the following options:

- Select GraphQL
- When asked if you have a schema, say No
- Select one of the default samples; you can change this later
- Choose to edit the schema and it will open the new `schema.graphql` in your editor

In this example, we are just adding a new property to our `Todo` model and save it:

```graphql
type Todo @model {
  id: ID!
  name: String!
  description: String
  completed: Boolean # 👈🏼 You just need to add this property. the others should be there already
}
```

> 🤔 If you want to learn more about GraphQL, you can go to the official documentation! 👉🏼 https://graphql.org/learn/

- after you safe your new GraphQL schema, you can see in the command line that all the resources has been created **locally**. Now you are ready to push all of it to our AWS account with the command:

```bash
$ amplify push
```

- Now lets go to the AWS Console to interact with our newly created GraphQL API:
 
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5i1btv2do5dgdsvx6qc.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q7nz1rwr2uodo8tfgfy4.png)

- Once you are there, you can search for your newly created GraphQL API, and click to view it
- If you click the `Schema` section, you will see the full generated schema
- Now click in `Queries` to start making our first queries withing the AWS console GraphQL Inspector


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nr9gy0ajuw3z6b9vwo52.jpg)

- You have the API documentation available on the right side of the UI

![AWS Appsync API Documentation Panel]
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fx64oajkvlzx10pxfkra.jpg)

- The documentations panel is interactive, you can go and click through all the Query and Mutation Definitions to check what is available to do with the API

> "The `Schema` is like a Restaurant menu, and a `Query` is like your order"
>
 

- 🤔 The Interface that let you execute queries, and mutations to a GraphQL API is called [GraphiQL](). It's (in my personal opinion) one of the greatest features about GraphQL as a tool. It makes very easy to test, document and interact with your GraphQL API. Checkout more info [here](https://github.com/graphql/graphiql).
- AWS Appsync has it Built-in in the Console to make it more accessible and setup to your needs. (that's awesome!)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/muwlzjejxkvwsncuwwsx.jpg)

Let's start by creating our first [`mutation`](https://graphql.org/learn/queries/#mutations) by typing the above code in the UI:

```graphql
mutation create {
  createTodo(
    input: {
      name: "Get Groceries"
      description: "Go to wal-mart"
      completed: false
    }
  ) {
    id
    name
    description
    complete
  }
}
```

- To execute the mutation, you can either click in the orange play button, or press enter while the cursor is at any point of the mutation


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60n4ruhxw7qochyj071k.jpg)
You can repeat the above process with different info as much as you want (in the video Nader creates two todos)

Now lets go and create our First Query

```graphql
query list {
  listTodos {
    items {
      id
      name
      description
      completed
    }
  }
}
```

- After you execute the query, you should see in the GraphiQL right side panel the result of the query, which is an array of all the available todos in the system.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7plbqudkoitws2xnfmji.jpg)

- Now that we got some data, we can go and query the data from our React app!
- In `App.js`, import `API` and `graphqlOperation` from `aws-amplify`

> 🤔 Remember that you need to [Configure your React App](03-react-native-use-the-aws-amplify-withauthenticator-hoc-to-implement-a-react-user-authorization-flow.md) in order to successfully connect your app with your AWS Amplify Services

```javascript
import { API, graphqlOperation } from "aws-amplify"
```

- Now copy the listTodos query from the AWS AppSync console and paste it in the component like so:

```javascript
const ListTodos = ` 
  query { 
    listTodos {
      items { 
        id name description completed 
      }
    }
  }
`
```

- and last lets glue all together in React

> ❗ the example above is using Functional components, not Class components  

```javascript
import React from 'react'
import { API, graphqlOperation } from "aws-amplify"

const ListTodos = `
  query {
    listTodos {
      items {
        id name description completed
      }
    }
  }
`

export default function App() {
  const [todos, setTodos] = React.useState([]) // important to initialize your state with an empty array!

  React.useEffect(() => {
    async function getTodos() {
      const todoData = await API.graphql(graphqlOperation(ListTodos)) // fetch the list of Todos from your graphQL API
      setTodos(toData.data.listTodos.items) // set the result from your query to your local state
    }

    getTodos() // Async functions are not permitted as `useEffect` functions parameters. that's why I created another async function inside of it instead
  }, [])

  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>
      {
        todos.map((todo, i)) => (
          <div>
            <h3>{todo.name}</h3>
            <p>{todo.description}</p>
          </div>
        ))
      }
    </div>
  );
}
```

- when this is ready, you can go to your command line and run `npm start` or `yarn start` and see the result in the browser ([http://localhost:3000/](http://localhost:3000/))


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3xtgri6qp193cridc3u.jpg)

# Part 6


## Create & Interact with a Serverless REST API with AWS Lambda from React

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here  that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 

## AWS Amplify !== AWS AppSync

[Appsync](https://aws.amazon.com/appsync/) is the AWS service focus on creating flexible APIs, and Amplify is the framework that combines multiple AWS tools to help you build any type of Application.

## Create a REST API

```bash
amplify add api
```

Select the following options:

```bash
? Please select from one of the below mentioned services: REST
? Provide a friendly name for your resource to be used as a label for this category in the project: peopleapi
? Provide a path (e.g., /items): /people (or whatever path you would like)
? Choose a Lambda source: Create a new Lambda function
? Provide a friendly name for your resource to be used as a label for this category in the project: peoplefunction
? Provide the AWS Lambda function name: peoplefunction
? Choose the function runtime that you want to use: NodeJS
? Choose the function template that you want to use: Serverless express function
? Do you want to access other resources created in this project from your Lambda function? y
```

- This should open your new Lambda function file to start editing (`/amplify/backend/function/peoplefunction/src/app.js`)
- Now go and replace the generated code on `app.get('/people', ...)` with the above code

```javascript
app.get('/people', function (req, res) {
  const people = [
    {name: "Nader". hair_color: 'brown'},
    {name: "Lilly". hair_color: 'black'},
    {name: "Victor". hair_color: 'blonde'}
  ]

  res.json({
    people
  })
});
```

- Save this file and go back to the command line and continue with the prompt questions

```
? Do you want to invoke this function on a recurring schedule? N
? Do you want to edit the local lambda function now? N
? Restrict API access: Y
? Who should have access? (Use arrow key)
❯ Authenticated users only
  Authenticated and Gest users
? What kind of access do you eant for Authenticated users (Use arrow key)
❯ read
  write
  read/write
? Do you want to add another path? N
```

- With the configuration setup, now you need to push it to your AWS Account with `amplify push`
- When this is finished, lets jump to `App.js`

> 🤔 Remember that you need to [Configure your React App](03-react-native-use-the-aws-amplify-withauthenticator-hoc-to-implement-a-react-user-authorization-flow.md) in order to successfully connect your app with your AWS Amplify Services

```javascript
import { API } from "aws-amplify"
```

- and last lets glue all together in React

> ❗ the example above is using Functional components, not Class components 

```javascript
import React from "react"
import { withAuthenticator } from "@aws-amplify/ui-react"
import { API } from "aws-amplify"

function App() {
  const [people, setPeople] = React.useState([]) // important to initialize your state with an empty array!

  React.useEffect(() => {
    async getPeople() {
    const data = await API.get('peopleapi', '/people')
    setPeople(data.people)
    }

    getPeople() // Async functions are not permitted as `useEffect` functions parameters. that's why I created another async function inside of it instead
  }, [])

  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>
    {
      people((person, i)) => (
        <div>
          <h3>{ perosn.name }</h3>
          <p>{ person.hair_color }</p>
        </div>
      ))
    }
    </div>
  );
}

export default withAuthenticator(App)
```

- when this is ready, you can go to your command line and run `npm start` or `yarn start` and see the result in the browser ([http://localhost:3000/](http://localhost:3000/))


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vzolfw3anxkwzntaaq6k.jpg)
- Now go one level further, and query data from another API and return it through our own API
- install `axios` as a dependency off your lambda function code, you should navigate to the function's package project and install it as below

```bash
cd amplify/backend/function/peoplefunction/src
yarn add axios
```

now open your Lambda function code (`/amplify/backend/function/peoplefunction/src/app.js`) and updated with the code below

```javascript
var axios = require("axios")

app.get("/people", function (req, res) {
  // const people = [
  //   {name: "Nader". hair_color: 'brown'},
  //   {name: "Lilly". hair_color: 'black'},
  //   {name: "Victor". hair_color: 'blonde'}
  // ]

  axios
    .get(`https://swapi.co/api/people/`)
    .then((response) => {
      const people = response.data.results
      res.json({
        people,
        error: null,
      })
    })
    .catch((err) => {
      res.json({
        error: err,
        people: null,
      })
    })
})
```

- save the file and go back to the command line
- With the Lambda function updated, you need to push it to your AWS Account again with the command `amplify push` (You should see the `Function` resource with the operation set to `Update`)
- when this is ready, you can go to your command line and run `npm start` or `yarn start` and see the result in the browser ([http://localhost:3000/](http://localhost:3000/))
- When the app loads, we should now see the data being returned from the Star Wars API.

![React App](https://res.cloudinary.com/hanii/image/upload/v1665366419/p8_t5lf0t.jpg)


# Part 7

## Store Data in Amazon S3 with React

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here   that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 
## What the freak is S3??

- from the [official docs](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js):

> AWS Amplify Storage module provides a simple mechanism for managing user content for your app in public, protected or private storage buckets. The Storage category comes with built-in support for Amazon S3.

- to get started with adding storage to our app, lets go to the command line and type:

```bash
amplify add storage

? Please select from one of the below mentioned services (Use arrow keys)
❯ Content (Images, audio, video, etc.)
  NoSQL Database
? Please provide a friendly name for your resource that will be used to lael this category in the project: <YOUR_PREFERED_NAME>
? Please provide a bucket name: <YOUR_PREFERED_NAME>
? Who should have access: (Use arrow key)
❯ Auth users only
  Auth and Guest users
? What kind of access do you want for Authenticated users (Use arrow key)
  read
  write
❯ read/write
```

- With the configuration setup, now you need to push it to your AWS Account with `amplify push`
- When this is finished, lets jump to `App.js`

> 🤔 Remember that you need to [Configure your React App](03-react-native-use-the-aws-amplify-withauthenticator-hoc-to-implement-a-react-user-authorization-flow.md) in order to successfully connect your app with your AWS Amplify Services

> ❗ the example above is using Functional components, not Class components  
```javascript
import React from "react"
import logo from "./logo.svg"
import "./App.css"
import { withAuthenticator } from "@aws-amplify/ui-react"
import { Storage } from "aws-amplify"

function App() {
  const [media, setMedia] = React.useState({})

  function handleChange(e) {
    const file = e.target.files[0]
    setMedia({
      fileUrl: URL.createObjectURL(file),
      file,
      filename: file.name,
    })
  }

  async function saveFile() {
    Storage.put(media.filename, media.file)
      .then(() => {
        console.log("successfully uploading file!")
        setMedia({})
      })
      .catch((err) => {
        console.log("error uploading file!", err)
      })
  }

  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>
      <input type="file" onChange={handleChange} />
      <img src={media.fileUrl} />
      <button onClick={saveFile}>Save File</button>
    </div>
  )
}

export default withAuthenticator(App)
```

- when this is ready, you can go to your command line and run `npm start` or `yarn start` and see the result in the browser ([http://localhost:3000/](http://localhost:3000/))
- When you add a file and save it, you should be able to see the successful message in the console

![React App](https://res.cloudinary.com/hanii/image/upload/v1665366418/p9_zz6dvo.jpg)

- The file should be in the bucket you just create it in your AWS Amazon account. You can search for it in the AWS Console

![AWS Console Bucket public folder]https://res.cloudinary.com/hanii/image/upload/v1665366417/p10_e4wez4.jpg)

- Copy one of the file's names to your clipboard, and go back to the `App.js` file. Lets see how we can retrieve a file from our bucket
- Lets update our code to the above:

```javascript
import React from "react"
import logo from "./logo.svg"
import "./App.css"
import { withAuthenticator } from "@aws-amplify/ui-react"
import { Storage } from "aws-amplify"

function App() {
  const [fileUrl, setFileUrl] = React.useState("")

  React.useEffect(() => {
    Storage.get("IMAGE_URL_YOU_COPIED")
      .then((data) => {
        setFileUrl(data)
      })
      .catch((err) => {
        console.log("error fetching image")
      })
  }, [])

  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>
      <img src={fileUrl} />
    </div>
  )
}

export default withAuthenticator(App)
```

- when this is ready, you can go to your command line and run `npm start` or `yarn start` and see the result in the browser ([http://localhost:3000/](http://localhost:3000/))
 

- amplify add storage
  - content
  - change name
  - use bucket name (unique)
  - auth users only
  - read/write
- amplify push
- in App.js add an input handler (follow the guide)
- open the bucket
- update the app to get files?
  - maybe check the guides and see what is up to date

 
# Final Part 


## Deploy Your React Application to AWS Using the Amplify CLI

> ❗ AWS Amplify is a framework in constant change and improvement. If you find something here  that is outdated, or not working, please make sure you check the [Official documentation](https://docs.amplify.aws/) to clear your doubts.
 

**It's time to publish our app!! 🎉**

- From teh [official docs](https://docs.amplify.aws/cli/hosting):

> Deploy and host your app using either Amplify Console or Amazon CloudFront/S3. The Amplify Console offers fully managed hosting with features such as instant cache invalidation and atomic deploys. For more control with setting up a CDN and hosting buckets, use CloudFront and S3.

```bash
amplify add hosting
? Select the environment setup: (Use arrow key)
❯ DEV (S3 only with HTTP)
  PROD (S3 with CloudFront using HTTPS)
? hosting bucket name
? index doc of the website `index.html`
? error doc of the website `index.html`
```

- when this is ready, you can go to your command line and run `amplify publish` to deploy our new setup
- Your app should launch in a new window!! 🎉

![React app Hosted](https://res.cloudinary.com/hanii/image/upload/v1665366418/p11_nif7u4.jpg)

 






















## References and Resources

- 🤔 [Official Docs Tutorial](https://docs.amplify.aws/start/getting-started/installation/q/integration/react#sign-up-for-an-aws-account)


- 🤔 [Official Docs Tutorial](https://docs.amplify.aws/start/getting-started/installation/q/integration/react#sign-up-for-an-aws-account)
- 🤔 [Official Docs: Add Authentication](https://docs.amplify.aws/start/getting-started/auth/q/integration/react)
- 🤔 [Official Docs: Configure your React app (frontend)](https://docs.amplify.aws/start/getting-started/setup/q/integration/react#set-up-frontend)
- 🤔 [Complete Auth Class API](https://aws-amplify.github.io/amplify-js/api/classes/authclass.html)
- 🤔 [Authentication Documentation](https://docs.amplify.aws/lib/auth/getting-started/q/platform/js#authentication-with-amplify)
- 🤔 [Amazon Cognito user Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html)


- 🤔 [Docs: Sign up, Sign in & Sign out](https://docs.amplify.aws/lib/auth/emailpassword/q/platform/js)
- 🤔 [Docs: Authentication Contepts](https://docs.amplify.aws/lib/auth/overview/q/platform/js)


- 🤔 [Create a GraphQL API (Official docs)](https://docs.amplify.aws/cli/graphql-transformer/overview#create-a-graphql-api)
- 🤔 [AWS AppSync main page](https://aws.amazon.com/appsync/)
-🤔  ["GraphQL Query Language" course](https://egghead.io/courses/graphql-query-language)
- 🤔 [Using Amplify GraphQL Client](https://docs.amplify.aws/lib/graphqlapi/query-data/q/platform/js#using-amplify-graphql-client)

- 🤔 [AWS Amplify Storage Official documentation](https://docs.amplify.aws/lib/storage/getting-started/q/platform/js)
- 🤔 [Storage Core Contepts](https://docs.amplify.aws/lib/storage/overview/q/platform/js)



- 🤔 [AWS Amplify Hosting](https://docs.amplify.aws/cli/hosting)