Connect to existing AWS resources with Amplify CLI
The AWS Amplify CLI (Command Line Interface) CLI provides a simple workflow for provisioning cloud resources like authentication, databases, and storage for apps through the command line.
In this guide, you will learn how to connect a new React web app to backend resources you've already created using the Amplify CLI.
Connect web app to existing AWS resources
This guide will walk you through connecting a new React web app to the AWS resources created with Amplify for an existing React app. If you don't already have an existing app, you can follow this React tutorial to create a to-do app that uses Amplify Auth, API, and Hosting resources.
Before you begin, you will need:
- An existing React app
- An AWS account: If you don't already have an account, follow the Setting Up Your AWS Environment tutorial for a quick overview.
- The Amplify CLI installed and configured.
- A text editor. For this guide, we will use VS Code, but you can use your preferred IDE.
Find the AWS backend details
Before connecting the backend resources to our new app, we first need to locate the details of the AWS environment provisioned for the existing app.
Step 1: In your existing app, open the file <Your-App>/amplify/team-provider-info.json
.
Step 2: In the team-provider-info.json
file, note the following:
- The environment you want to use
- The
AmplifyAppId
for the required environment
Create the React app
Now that we have gathered the necessary backend details, we can start building out the new React app.
Step 1: Create a React app by running the following command in your terminal.
npx create-react-app react-amplify-connect
Step 2: Open the newly created React app using VS Code by running the following commands in your terminal.
1cd react-amplify-connect2code . -r
Step 3: Navigate to the app's root folder and import the Amplify backend for the app by running the following command in your terminal.
amplify pull --appId <The_App_ID> --envName <The_App_Env>
Step 4: Select the AWS Authentication method. In this example, we are using an AWS profile. Ensure that the selected profile has the necessary permissions to access and modify AWS resources. See Configure the Amplify CLI for more information on setting up your AWS profile.
Accept the default values for the prompts and make sure to answer Yes to the “modifying this backend” question. Amplify CLI will initialize the backend and connect the project to the cloud.
1? Select the authentication method you want to use: AWS profile2
3For more information on AWS Profiles, see:4https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html5
6? Please choose the profile you want to use AwsWest17Amplify AppID found: dfn3u8j1nvzjc. Amplify App name is: reactamplified8Backend environment dev found in Amplify Console app: reactamplified9? Choose your default editor: Visual Studio Code10✔ Choose the type of app that you're building · javascript11Please tell us about your project12? What javascript framework are you using react13? Source Directory Path: src14? Distribution Directory Path: build15? Build Command: npm run-script build16? Start Command: npm run-script start17? Do you plan on modifying this backend? Yes18⠋ Fetching updates to backend environment: dev from the cloud.19⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules20
21⠇ Fetching updates to backend environment: dev from the cloud.✅ GraphQL schema compiled successfully.22
23Edit your schema at /Users/malakamm/development/react-amplify-connect/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /Users/malakamm/development/react-amplify-connect/amplify/backend/api/reactamplified/schema24✔ Successfully pulled backend environment dev from the cloud.25Browserslist: caniuse-lite is outdated. Please run:26 npx update-browserslist-db@latest27 Why you should do it regularly: https://github.com/browserslist/update-db#readme28✅ 29
30✅ Successfully pulled backend environment dev from the cloud.31Run 'amplify pull' to sync future upstream changes.
The Amplify CLI will add a new folder named amplify
to the app's root folder, which contains the Amplify project and backend details.
Step 5: Use the following command to generate the GraphQL statements.
amplify codegen add
Step 6: Accept the default values of the prompts.
1? Choose the code generation language target javascript2? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js3? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes4? Enter maximum statement depth [increase from default if your schema is deeply nested] 25✔ Generated GraphQL operations successfully and saved at src/graphql
The CLI will add a new folder named graphql
to the app's root folder, which contains the GraphQL statements.
Step 7: Install the aws-amplify and @aws-amplify/ui-react packages by running the following commands.
npm install aws-amplify @aws-amplify/ui-react
Step 8: Update the App.js
file with the following code to create a login flow using Amplify UI and a form with a button to create to-dos, as well as a way to fetch and render the list of to-dos.
1import React, { useEffect, useState } from 'react'2import { Amplify, API, graphqlOperation } from 'aws-amplify'3import { createTodo } from './graphql/mutations'4import { listTodos } from './graphql/queries'5import { withAuthenticator, Button, Heading } from '@aws-amplify/ui-react';6import '@aws-amplify/ui-react/styles.css';7
8import awsExports from "./aws-exports";9Amplify.configure(awsExports);10
11const initialState = { name: '', description: '' }12
13const App = ({ signOut, user }) => {14 const [formState, setFormState] = useState(initialState)15 const [todos, setTodos] = useState([])16
17 useEffect(() => {18 fetchTodos()19 }, [])20
21 function setInput(key, value) {22 setFormState({ ...formState, [key]: value })23 }24
25 async function fetchTodos() {26 try {27 const todoData = await API.graphql(graphqlOperation(listTodos))28 const todos = todoData.data.listTodos.items29 setTodos(todos)30 } catch (err) { console.log('error fetching todos') }31 }32
33 async function addTodo() {34 try {35 if (!formState.name || !formState.description) return36 const todo = { ...formState }37 setTodos([...todos, todo])38 setFormState(initialState)39 await API.graphql(graphqlOperation(createTodo, {input: todo}))40 } catch (err) {41 console.log('error creating todo:', err)42 }43 }44
45 return (46 <div style={styles.container}>47 <Heading level={1}>Hello {user.username}</Heading>48 <Button onClick={signOut} style={styles.button}>Sign out</Button>49 <h2>Amplify Todos</h2>50 <input51 onChange={event => setInput('name', event.target.value)}52 style={styles.input}53 value={formState.name}54 placeholder="Name"55 />56 <input57 onChange={event => setInput('description', event.target.value)}58 style={styles.input}59 value={formState.description}60 placeholder="Description"61 />62 <button style={styles.button} onClick={addTodo}>Create Todo</button>63 {64 todos.map((todo, index) => (65 <div key={todo.id ? todo.id : index} style={styles.todo}>66 <p style={styles.todoName}>{todo.name}</p>67 <p style={styles.todoDescription}>{todo.description}</p>68 </div>69 ))70 }71 </div>72 )73}74
75const styles = {76 container: { width: 400, margin: '0 auto', display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 20 },77 todo: { marginBottom: 15 },78 input: { border: 'none', backgroundColor: '#ddd', marginBottom: 10, padding: 8, fontSize: 18 },79 todoName: { fontSize: 20, fontWeight: 'bold' },80 todoDescription: { marginBottom: 0 },81 button: { backgroundColor: 'black', color: 'white', outline: 'none', fontSize: 18, padding: '12px 0px' }82}83
84export default withAuthenticator(App);
Step 9: Run the app using the following command.
npm start
Step 10: Change the UI of the app as shown in the following to update the placeholder text of the to-do form and to use the user’s email for the hello message.
1...2 return (3 <div style={styles.container}>4 <Heading level={1}>Hello {*user*.attributes.email}</Heading>5 <Button onClick={signOut} style={styles.button}>Sign out</Button>6 <h2>Amplify Todos</h2>7 <input8 onChange={event => setInput('name', event.target.value)}9 style={styles.input}10 value={formState.name}11 placeholder="ToDo Name"12 />13 <input14 onChange={event => setInput('description', event.target.value)}15 style={styles.input}16 value={formState.description}17 placeholder="ToDo Description"18 />19 <button style={styles.button} onClick={addTodo}>Create Todo</button>20 {21 todos.map((todo, index) => (22 <div key={todo.id ? todo.id : index} style={styles.todo}>23 <p style={styles.todoName}>{todo.name}</p>24 <p style={styles.todoDescription}>{todo.description}</p>25 </div>26 ))27 }28 </div>29 )30....
The App.js
file should now look like the following code snippet.
1import React, { useEffect, useState } from 'react'2import { Amplify, API, graphqlOperation } from 'aws-amplify'3import { createTodo } from './graphql/mutations'4import { listTodos } from './graphql/queries'5import { withAuthenticator, Button, Heading } from '@aws-amplify/ui-react';6import '@aws-amplify/ui-react/styles.css';7
8import awsExports from "./aws-exports";9Amplify.configure(awsExports);10
11const initialState = { name: '', description: '' }12
13const App = ({ signOut, user }) => {14 const [formState, setFormState] = useState(initialState)15 const [todos, setTodos] = useState([])16
17 useEffect(() => {18 fetchTodos()19 }, [])20
21 function setInput(key, value) {22 setFormState({ ...formState, [key]: value })23 }24
25 async function fetchTodos() {26 try {27 const todoData = await API.graphql(graphqlOperation(listTodos))28 const todos = todoData.data.listTodos.items29 setTodos(todos)30 } catch (err) { console.log('error fetching todos') }31 }32
33 async function addTodo() {34 try {35 if (!formState.name || !formState.description) return36 const todo = { ...formState }37 setTodos([...todos, todo])38 setFormState(initialState)39 await API.graphql(graphqlOperation(createTodo, {input: todo}))40 } catch (err) {41 console.log('error creating todo:', err)42 }43 }44
45 return (46 <div style={styles.container}>47 <Heading level={1}>Hello {user.attributes.email}</Heading>48 <Button onClick={signOut} style={styles.button}>Sign out</Button>49 <h2>Amplify Todos</h2>50 <input51 onChange={event => setInput('name', event.target.value)}52 style={styles.input}53 value={formState.name}54 placeholder="ToDo Name"55 />56 <input57 onChange={event => setInput('description', event.target.value)}58 style={styles.input}59 value={formState.description}60 placeholder="ToDo Description"61 />62 <button style={styles.button} onClick={addTodo}>Create Todo</button>63 {64 todos.map((todo, index) => (65 <div key={todo.id ? todo.id : index} style={styles.todo}>66 <p style={styles.todoName}>{todo.name}</p>67 <p style={styles.todoDescription}>{todo.description}</p>68 </div>69 ))70 }71 </div>72 )73}74
75const styles = {76 container: { width: 400, margin: '0 auto', display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 20 },77 todo: { marginBottom: 15 },78 input: { border: 'none', backgroundColor: '#ddd', marginBottom: 10, padding: 8, fontSize: 18 },79 todoName: { fontSize: 20, fontWeight: 'bold' },80 todoDescription: { marginBottom: 0 },81 button: { backgroundColor: 'black', color: 'white', outline: 'none', fontSize: 18, padding: '12px 0px' }82}83
84export default withAuthenticator(App);
Step 11: Use the following command to publish your changes. Amplify CLI will publish the changes and display the app URL.
amplify publish
Step 12: Use the URL to run the app in the browser.
Conclusion
Congratulations! Your new React app is now connected to AWS resources from a different app through AWS Amplify. This integration grants your app access to authentication resources for user management, a scalable GraphQL API backed by Amazon DynamoDB, and a hosting service for publishing your app to the cloud.
Clean up resources
Once you're finished experimenting with this demo app, we recommend deleting the backend resources to avoid incurring unexpected costs. You can do this by running the following command in the root folder of the app.
amplify delete
If you would like to expand this demo app into a production-ready app, you may need to add additional resources, such as authorization and storage. Refer to the Build & connect backend section for guides on how to add and connect other backend resources.