<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sahan Amarsha</title>
    <description>The latest articles on DEV Community by Sahan Amarsha (@dev_sahan).</description>
    <link>https://dev.to/dev_sahan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F369483%2F6e77d5d8-405d-417f-849f-7c873de0b5b7.jpg</url>
      <title>DEV Community: Sahan Amarsha</title>
      <link>https://dev.to/dev_sahan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dev_sahan"/>
    <language>en</language>
    <item>
      <title>Complete Guide to AWS Amplify and React Native</title>
      <dc:creator>Sahan Amarsha</dc:creator>
      <pubDate>Fri, 22 Jan 2021 20:57:24 +0000</pubDate>
      <link>https://dev.to/dev_sahan/complete-guide-to-aws-amplify-and-react-native-4on5</link>
      <guid>https://dev.to/dev_sahan/complete-guide-to-aws-amplify-and-react-native-4on5</guid>
      <description>&lt;h4&gt;
  
  
  Let’s Build an E-commerce App with ReactNative and Amplify
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Click &lt;a href="https://youtu.be/NqYQ0Muwf3c" rel="noopener noreferrer"&gt;here&lt;/a&gt; to see the video walkthrough.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Table of Content
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Introduction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting Up the Project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding Cognito Authentication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding AppSync API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding S3 Storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieving AppSync Data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conclusion&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  01. Introduction
&lt;/h1&gt;

&lt;p&gt;Hello! &amp;amp; Welcome to this complete guide on AWS Amplify and React Native. In this tutorial, we will build a simple e-commerce app. Users can log in/signup to this app. Users can add their own products, and all the users can view those products added by different users. &lt;/p&gt;

&lt;p&gt;Here is a quick demo,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw7qjm1ix8bqr6rp863pb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw7qjm1ix8bqr6rp863pb.jpg"&gt;&lt;/a&gt;&lt;br&gt;Different Screens in Mobile App
  &lt;/p&gt;

&lt;p&gt;Even though this is not a very complex application, this will be a perfect starter project for you. We will use different AWS Services like S3 Storage, AWS AppSync API, and Amazon Cognito Authentication. Don’t worry I will explain these in detail, later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Diagram
&lt;/h2&gt;

&lt;p&gt;The following diagram demonstrates our AWS Architecture Diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyz3l2dv9wki6uahjakv2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyz3l2dv9wki6uahjakv2.jpg"&gt;&lt;/a&gt;&lt;br&gt;AWS Architecture Diagram for Mobile App
  &lt;/p&gt;

&lt;p&gt;AWS Amplify makes it much easier to work with these different services. As always, our backend resources will be created and managed by Amplify. Let me explain what these services will do.&lt;/p&gt;

&lt;p&gt;So, Amplify is the heart of our backend environment. Those arrows pointing from Amplify means that we will use Amplify to connect those different resources. Every product will have an image. We will store that image in an &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;S3&lt;/a&gt; Bucket. Product details will be saved in Amazon &lt;a href="https://aws.amazon.com/dynamodb/" rel="noopener noreferrer"&gt;DynamoDB&lt;/a&gt;, a NoSQL database provided by AWS. To talk with that Database, we will use a GraphQL API provided by AWS &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;AppSync&lt;/a&gt;. Amazon Cognito will handle authentication.&lt;/p&gt;

&lt;p&gt;Ready to build the app? Let’s get started. 👷🏽‍♂️🧰&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To avoid any disturbances in the future, make sure you have the following prerequisites installed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; v10.x or later&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.npmjs.com/cli/v6/commands/npm-install" rel="noopener noreferrer"&gt;npm&lt;/a&gt; v5.x or later&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.amplify.aws/cli/start/install" rel="noopener noreferrer"&gt;Amplify CLI&lt;/a&gt; (version @4.40.1, what I’m using in the tutorial)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.android.com/studio" rel="noopener noreferrer"&gt;Android Studio&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ReactNatice CLI (version 2.0.1)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  02. Setting Up the Project
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Installing and Configuring Amplify CLI
&lt;/h2&gt;

&lt;p&gt;Through this tutorial, we will work with AWS Amplify CLI. You can install it by running,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install -g @aws-amplify/cli@4.39.0


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then you need to run &lt;code&gt;amplify configure&lt;/code&gt;. This will set up your Amplify CLI. There you will set up a new IAM User. You will finish setting up your IAM User, by providing the &lt;code&gt;accessKeyId&lt;/code&gt; and &lt;code&gt;secretAccessKey&lt;/code&gt; for your IAM user.&lt;/p&gt;

&lt;p&gt;If you are stuck at some point, you can refer to this original guideline on installing Amplify CLI, &lt;a href="https://docs.amplify.aws/cli/start/install" rel="noopener noreferrer"&gt;https://docs.amplify.aws/cli/start/install&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a New ReactNative Application
&lt;/h2&gt;

&lt;p&gt;Hope you have installed and configured Amplify CLI.&lt;/p&gt;

&lt;p&gt;To work with ReactNative, you will have to set up the Android development environment. You can refer to this original guide, &lt;a href="https://reactnative.dev/docs/environment-setup" rel="noopener noreferrer"&gt;https://reactnative.dev/docs/environment-setup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s create a new React Native app called AmplifyShop.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx react-native init amplify_shop


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you have already installed &lt;code&gt;react-native-cli&lt;/code&gt;, you can use that instead of &lt;code&gt;npx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the newly created React Native Project using Android Studio. Open the Android Emulator using Android Studio’s AVD Manager. In the project directory, run these two commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx react-native start 
npx react-native run-android


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, the React Native project should run on your Android Emulator. If you are stuck at some point, please refer to the guide that I have suggested earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing Amplify Backend
&lt;/h2&gt;

&lt;p&gt;Let’s initialize Amplify for our project. Then we can add services one by one.&lt;/p&gt;

&lt;p&gt;In the project directory, run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

amplify init


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then you will be prompted for the following information regarding the project you initialize.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkzlkqwvh0kz8qehnkjwg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkzlkqwvh0kz8qehnkjwg.jpg"&gt;&lt;/a&gt;&lt;br&gt;Running 'amplify init'
  &lt;/p&gt;

&lt;p&gt;When you initialize your Amplify Project,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It creates a file called &lt;code&gt;aws-exports.js&lt;/code&gt; in the src directory. This file will store all the relevant information to identify the AWS resources/services that will allocate in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It creates a directory called &lt;code&gt;amplify&lt;/code&gt;. We will use this directory to store the templates and configuration details of the services that we will use in the future. In this directory, Amplify will hold our backend schema as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It creates a Cloud Project. That project can be viewed using the &lt;code&gt;amplify console&lt;/code&gt; command.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, we need to install all the necessary dependencies by running the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install aws-amplify aws-amplify-react-native amazon-cognito-identity-js @react-native-community/netinfo


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You will also need to install the pod dependencies for iOS.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx pod-install


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Configuring Amplify Backend
&lt;/h2&gt;

&lt;p&gt;To complete setting up our Amplify project, we need to configure amplify in a higher-order component. Adding the following lines of code in your &lt;code&gt;App.js&lt;/code&gt; or &lt;code&gt;index.js&lt;/code&gt; file will do the job.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';

Amplify.configure({
  ...awsconfig,
  Analytics: {
    disabled: true,
  },
});


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That completes setting up the project. Now let’s add those services one by one.&lt;/p&gt;

&lt;h1&gt;
  
  
  03. Adding Cognito Authentication
&lt;/h1&gt;

&lt;p&gt;Now, adding Authentication to your React Native App never gets easier than Amplify.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Sign-up and Log-in
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;amplify add auth&lt;/code&gt; in your project directory. Submit the following information when configuring Authentication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fksng76rmodeldkklvk5i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fksng76rmodeldkklvk5i.jpg"&gt;&lt;/a&gt;&lt;br&gt;Running 'amplify add auth'
  &lt;/p&gt;

&lt;p&gt;Then, run &lt;code&gt;amplify push&lt;/code&gt;, to deploy your backend changes. Amplify will take care of the rest by creating your &lt;a href="https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html" rel="noopener noreferrer"&gt;Cognito Userpool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The authentication UI component, provided by Amplify Framework, will provide the entire authentication flow. &lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;App.js&lt;/code&gt; file,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import &lt;code&gt;withAuthenticator&lt;/code&gt; component&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { withAuthenticator } from 'aws-amplify-react-native'


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Wrap the main component with &lt;code&gt;withAuthenticator&lt;/code&gt; component.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export default withAuthenticator(App)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When you run your app. This login screen will show up. Try logging in as a new user. This will lead you to the home page. The newly created user will be saved in our Cognito User Pool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frj4sw9suaap24rimbdxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frj4sw9suaap24rimbdxf.png"&gt;&lt;/a&gt;&lt;br&gt;Sign-in Screen by Amplify
  &lt;/p&gt;

&lt;p&gt;Before Adding AppSync API, let’s add navigation to our App. &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding ReactNative Navigation
&lt;/h2&gt;

&lt;p&gt;Our App will contain two screens. One Screen to display the list of products and the other to add new products. Let’s create these two screens. &lt;/p&gt;

&lt;p&gt;Create a new directory called &lt;code&gt;src&lt;/code&gt;. In that directory, create a folder called &lt;code&gt;screens&lt;/code&gt;. In that folder &lt;code&gt;src/screens&lt;/code&gt;, create two new javascript files named &lt;code&gt;add-product-screen.js&lt;/code&gt; and &lt;code&gt;home-screen.js&lt;/code&gt; I just prefer this naming convention. You can use any convention.&lt;/p&gt;

&lt;p&gt;Copy and paste the following sample code. Do change the function name (‘HomeScreen’ and ‘AddProductScreen’) and the title according to the page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;directory: src/screens/ home.js, add-product-screen.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from 'react';
import {SafeAreaView, StatusBar, Text} from 'react-native';

const HomeScreen = (props) =&amp;gt; {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;StatusBar barStyle="dark-content" /&amp;gt;
      &amp;lt;SafeAreaView&amp;gt;
        &amp;lt;Text&amp;gt;Home&amp;lt;/Text&amp;gt;
      &amp;lt;/SafeAreaView&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

export default HomeScreen;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are multiple ways to add navigation into ReactNative Apps. In this tutorial, we will use ‘Stack Navigator Library’ from React Navigation. First, we should install it using npm.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install @react-navigation/native


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Install all the additional third-party dependencies as well.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view @react-navigation/stack


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From React Native 0.60 and higher, &lt;a href="https://github.com/react-native-community/cli/blob/master/docs/autolinking.md" rel="noopener noreferrer"&gt;linking is automatic&lt;/a&gt;. So you don’t need to run &lt;code&gt;react-native link&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you’re on a Mac and developing for iOS, you need to install the pods (via &lt;a href="https://cocoapods.org/" rel="noopener noreferrer"&gt;Cocoapods&lt;/a&gt;) to complete the linking.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx pod-install ios


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To finish installing React Native Navigation, add the following import in your &lt;code&gt;App.js&lt;/code&gt; or &lt;code&gt;index.js&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import 'react-native-gesture-handler';


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For the sake of this tutorial, I will use two additional styling libraries. I will use &lt;code&gt;react-native-elements&lt;/code&gt; and &lt;code&gt;react-native-vector-icons&lt;/code&gt;. Let’s install those using npm.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install react-native-elements
npm install react-native-vector-icons


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In order to view &lt;code&gt;fontawesome icons&lt;/code&gt;, we need to add the following line into android/app/&lt;strong&gt;build.gradle&lt;/strong&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With that out of the way, move into &lt;code&gt;App.js&lt;/code&gt; file. We will use the &lt;code&gt;App.js&lt;/code&gt; file to set up navigation in our App. Replace the current code with the following.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;directory: App.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from 'react';
import {StyleSheet, View, TouchableOpacity} from 'react-native';
import {createStackNavigator} from '@react-navigation/stack';
import {NavigationContainer} from '@react-navigation/native';
import AddProductScreen from './src/screens/add-product-screen';
import HomeScreen from './src/screens/home-screen';
import {Button} from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import {withAuthenticator} from 'aws-amplify-react-native';

const App: () =&amp;gt; React$Node = () =&amp;gt; {
  const Stack = createStackNavigator();
  return (
    &amp;lt;&amp;gt;
      &amp;lt;NavigationContainer&amp;gt;
        &amp;lt;Stack.Navigator initialRouteName="Home"&amp;gt;
          &amp;lt;Stack.Screen
            name="Home"
            component={HomeScreen}
            options={({navigation}) =&amp;gt; ({
              title: 'Home',
              headerStyle: {
                backgroundColor: '#ff9300',
              },
              headerRight: () =&amp;gt; (
                &amp;lt;TouchableOpacity
                  style={styles.addButton}
                  onPress={() =&amp;gt; navigation.navigate('AddProduct')}&amp;gt;
                  &amp;lt;Icon name={'plus'} size={20} color="#000000" /&amp;gt;
                &amp;lt;/TouchableOpacity&amp;gt;
              ),
            })}
          /&amp;gt;
          &amp;lt;Stack.Screen
            name="AddProduct"
            buttonStyle={styles.addButton}
            component={AddProductScreen}
            options={{
              title: 'Add Product',
              headerStyle: {
                backgroundColor: '#ff9300',
              },
            }}
          /&amp;gt;
        &amp;lt;/Stack.Navigator&amp;gt;
      &amp;lt;/NavigationContainer&amp;gt;
    &amp;lt;/&amp;gt;
  );
};
const styles = StyleSheet.create({
  addButton: {
    marginRight: 20,
  },
  logOutBtn: {
    marginLeft: 10,
  },
});

export default withAuthenticator(App);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is the simplest and easiest way to add navigation. We got &lt;code&gt;Stack.Navigator&lt;/code&gt; Component, which we can provide an initial route. Inside that wrapper component, we can define each screen using the &lt;code&gt;Stack.Screen&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;We can use that &lt;code&gt;options&lt;/code&gt; prop to define the header for each screen. I just added a navigation button on the right side of our header. It should navigate to our AddProduct Screen.&lt;/p&gt;

&lt;p&gt;Since we are using Stack Navigation, the new screen gets loaded on top of the previous screen. Therefore, the back button will be added automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Sign-Out Option
&lt;/h2&gt;

&lt;p&gt;How about adding a sign-out option to our Home Screen. We are already passing &lt;code&gt;headerRight&lt;/code&gt; to our home screen. We can pass another prop called &lt;code&gt;headerLeft&lt;/code&gt;. This will create a new button on the left side of our header.&lt;/p&gt;

&lt;p&gt;Do paste in the following code along with the import.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// importing Auth Class from Amplify Library
import {Auth} from 'aws-amplify';
headerLeft: () =&amp;gt; (
  &amp;lt;View style={styles.logOutBtn}&amp;gt;
    &amp;lt;Button
      icon={&amp;lt;Icon name="sign-out" size={25} color="#000000" /&amp;gt;}
      onPress={}
      type="clear"
    /&amp;gt;
  &amp;lt;/View&amp;gt;
),


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Sign-out button will trigger, &lt;code&gt;Auth.signOut()&lt;/code&gt; method. This method will end the user’s login session. When the session is over, the login-screen gets loaded automatically.  We don’t need to manage any state variable. Amplify will do the authentication session handling.&lt;/p&gt;

&lt;p&gt;So, that’s it for Navigation. Learn more about React Native Navigation &lt;a href="https://reactnavigation.org/docs/getting-started" rel="noopener noreferrer"&gt;here&lt;/a&gt;. In the end, the result should be something like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcd9axmc2073qvab48tb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcd9axmc2073qvab48tb8.png"&gt;&lt;/a&gt;&lt;br&gt;After Adding Navigation
  &lt;/p&gt;

&lt;h1&gt;
  
  
  04. Adding AppSync API
&lt;/h1&gt;

&lt;p&gt;Let’s store details about products by adding an AppSync API. We will save details about products such as name, price, and description. We will also add an image to every product. Let’s keep that image option for later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Executing ‘amplify add api’
&lt;/h2&gt;

&lt;p&gt;As I’ve said earlier, through AppSync, we can build a &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL API&lt;/a&gt;. All the heavy lifting, such as connecting and creating DynamoDB tables, generation queries, and mutations, will be done by &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;AppSync&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s started by provisioning an AppSync API for our Amplify Backend. Execute,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

amplify add api


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and you will be prompted for the following information. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmzh5a7xmrec0lbaswapm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmzh5a7xmrec0lbaswapm.png"&gt;&lt;/a&gt;&lt;br&gt;Running 'amplify add api'
  &lt;/p&gt;

&lt;p&gt;Just accept the defaults. &lt;/p&gt;

&lt;h2&gt;
  
  
  Editing GraphQL Schema
&lt;/h2&gt;

&lt;p&gt;Let’s edit our schema. You will find our &lt;code&gt;schema.graphql&lt;/code&gt; file in &lt;code&gt;amplify/backend/api/schema.graphql&lt;/code&gt; directory. Copy and paste the following schema.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

type Product
@model(subscriptions: null)
@auth(
  rules: [
    { allow: owner },
    { allow: private, operations: [read] }
  ]) {
  id: ID!
  name: String!
  description: String
  price: Float
  userId: String
  userName: String
  image: String
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save the file. Follow with an &lt;code&gt;amplify push&lt;/code&gt; to deploy your changes into AWS Cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcxij1fciolzb2pl48gxg.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcxij1fciolzb2pl48gxg.JPG"&gt;&lt;/a&gt;&lt;br&gt;Running 'amplify push' after adding AppSync API
  &lt;/p&gt;

&lt;p&gt;Now, our AppSync API has been created. Also, the AppSync Library automatically created queries, mutations for our GraphQL Schema. Run &lt;code&gt;amplify api console&lt;/code&gt; to view your AppSync API in AWS.&lt;/p&gt;

&lt;p&gt;You could play around with some GraphQL operations in this AWS AppSync Console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd35btwxr1lox5nrb32xc.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd35btwxr1lox5nrb32xc.JPG"&gt;&lt;/a&gt;&lt;br&gt;AWS AppSync Console
  &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding AddProduct Screen
&lt;/h2&gt;

&lt;p&gt;Let’s start interacting with our AppSync API.&lt;/p&gt;

&lt;p&gt;Before that, I want to add an extra package that will help in creating a React Native Form. With the &lt;a href="https://www.npmjs.com/package/tcomb-form-native" rel="noopener noreferrer"&gt;tcomb-form-native&lt;/a&gt; package, you can quickly create a form on the fly. So, let’s install it using npm.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install tcomb-form-native


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Copy and paste the following code into our add-product-screen.js file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;directory: src/screens/add-product-screen.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React, {useState} from 'react';
import {StyleSheet, SafeAreaView, ScrollView} from 'react-native';
import {Button} from 'react-native-elements';
import t from 'tcomb-form-native';
const Form = t.form.Form;
const User = t.struct({
  name: t.String,
  price: t.Number,
  description: t.String,
});
const AddProductScreen = ({navigation}) =&amp;gt; {
  const [form, setForm] = useState(null); 
  const [initialValues, setInitialValues] = useState({});

  const options = {
    auto: 'placeholders',
    fields: {
      description: {
        multiLine: true,
        stylesheet: {
          ...Form.stylesheet,
          textbox: {
            ...Form.stylesheet.textbox,
            normal: {
              ...Form.stylesheet.textbox.normal,
              height: 100,
              textAlignVertical: 'top',
            },
          },
        },
      },
    },
  };
const handleSubmit = async () =&amp;gt; {
    // Saving product details
  };
return (
    &amp;lt;&amp;gt;
      &amp;lt;SafeAreaView style={styles.addProductView}&amp;gt;
        &amp;lt;ScrollView&amp;gt;
          &amp;lt;Form
            ref={(c) =&amp;gt; setForm(c)}
            value={initialValues}
            type={User}
            options={options}
          /&amp;gt;
          &amp;lt;Button title="Save" onPress={handleSubmit} /&amp;gt;
        &amp;lt;/ScrollView&amp;gt;
      &amp;lt;/SafeAreaView&amp;gt;
    &amp;lt;/&amp;gt;
  );
};
const styles = StyleSheet.create({
  addProductView: {
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    paddingTop: 15,
    height: 'auto',
  },
});
export default AddProductScreen;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Try running your app, you should see a form just like this.&lt;/p&gt;

&lt;p&gt;Let’s inspect our code.&lt;/p&gt;

&lt;p&gt;You can see that, I didn't use any &lt;code&gt;textInputs&lt;/code&gt;. I just defined our fields using &lt;code&gt;t.struct&lt;/code&gt; and only since the description is a multiple &lt;code&gt;textInput&lt;/code&gt;, we need to pass in extra options.&lt;/p&gt;

&lt;p&gt;In our &lt;code&gt;handleSubmit&lt;/code&gt; function, we are saving entered details in the database. Paste in the following code inside our &lt;code&gt;handleSubmit&lt;/code&gt; function. Don’t forget the imports.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { Auth, API, graphqlOperation} from 'aws-amplify';
import {createProduct} from '../../graphql/mutations';

try {
      const value = await form.getValue();
      const user = await Auth.currentAuthenticatedUser();
const response = await API.graphql(
        graphqlOperation(createProduct, {
          input: {
            name: value.name,
            price: value.price.toFixed(2),
            description: value.description,
            userId: user.attributes.sub,
            userName: user.username,
          },
        }),
      );
      console.log('Response :\n');
      console.log(response);
    } catch (e) {
      console.log(e.message);
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Auth.currentAuthenticatedUser()&lt;/code&gt; will do exactly what the name suggests. It will return details about the logged-in user. Cognito gives every user an attribute called &lt;code&gt;sub&lt;/code&gt;, a unique string value. We will save that as the userId assigned to a product. Username will showcase the product owner.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createProduct&lt;/code&gt; mutation was generated automatically. Here we are referring to that mutation, which was defined in &lt;code&gt;graphql/mutations.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Now, after running the app and saving a product, you should see a console.log of the response. You could also query in the AWS AppSync Console.&lt;/p&gt;

&lt;h1&gt;
  
  
  05. Adding S3 Storage
&lt;/h1&gt;

&lt;p&gt;Now by far, users can save product details. We should also add an extra option to upload a product image. We will need an S3 Bucket to store product images. Working with S3 really gets easier with Amplify. Let me show you.&lt;/p&gt;

&lt;p&gt;Before that, install the &lt;a href="https://www.npmjs.com/package/react-native-image-picker" rel="noopener noreferrer"&gt;React Native image picker library&lt;/a&gt;. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install react-native-image-picker


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;RN &amp;gt;= 0.60&lt;br&gt;
    cd ios &amp;amp;&amp;amp; pod install&lt;/p&gt;

&lt;p&gt;RN &amp;lt; 0.60&lt;br&gt;
    react-native link react-native-image-picker&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For now, this image picker library will support only 21 or newer SDK Versions. So edit &lt;strong&gt;minSDK version&lt;/strong&gt; in &lt;strong&gt;&lt;em&gt;android/build.gradle&lt;/em&gt;&lt;/strong&gt; file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;buildToolsVersion = "29.0.2"&lt;br&gt;
    &lt;strong&gt;minSdkVersion = 21&lt;/strong&gt;&lt;br&gt;
    compileSdkVersion = 29&lt;br&gt;
    targetSdkVersion = 29&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Executing ‘amplify add storage’
&lt;/h2&gt;

&lt;p&gt;Run,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

amplify add storage


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;to create a new S3 Bucket. Accept the defaults in the prompt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9lqgpqe3nrltgwyy7oo7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9lqgpqe3nrltgwyy7oo7.png"&gt;&lt;/a&gt;&lt;br&gt;Running 'amplify add storage'
  &lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;amplify push&lt;/code&gt;, to deploy your changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating the Form
&lt;/h2&gt;

&lt;p&gt;Let’s add image uploading and previewing options into our form. I build a fancy ImageUploader Component with an image preview. Make sure to add that by making a new &lt;code&gt;components&lt;/code&gt; directory in the &lt;code&gt;src&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;directory: src/components/ImageUploader.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from 'react';
import {View, Image, Button, StyleSheet} from 'react-native';

const ImageUploader = ({handleChoosePhoto, photo}) =&amp;gt; {
  return (
    &amp;lt;View style={styles.imageView}&amp;gt;
      {photo &amp;amp;&amp;amp; &amp;lt;Image source={{uri: photo.uri}} style={styles.photo} /&amp;gt;}
      &amp;lt;Button
        style={styles.photoBtn}
        title="Choose Photo"
        onPress={handleChoosePhoto}
      /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

const styles = StyleSheet.create({
  imageView: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    paddingBottom: 15,
  },
  photo: {
    width: 200,
    height: 200,
  },
});

export default ImageUploader;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In order to use this image uploading option, we will make the following changes in our &lt;code&gt;add-product-screen.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;We will add the extra ImageUploader Component inside our ScrollView Component.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

return (
  &amp;lt;&amp;gt;
    &amp;lt;SafeAreaView style={styles.addProductView}&amp;gt;
      &amp;lt;ScrollView&amp;gt;
        &amp;lt;Form
          ref={(c) =&amp;gt; setForm(c)}
          value={initialValues}
          type={User}
          options={options}
        /&amp;gt;
        &amp;lt;ImageUploader photo={photo} handleChoosePhoto={handleChoosePhoto} /&amp;gt;
        &amp;lt;Button title="Save" onPress={handleSubmit} /&amp;gt;
      &amp;lt;/ScrollView&amp;gt;
    &amp;lt;/SafeAreaView&amp;gt;
  &amp;lt;/&amp;gt;
);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Declare this state variable along with the new handleChoosePhoto function.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const [photo, setPhoto] = useState(null);
const handleChoosePhoto = async () =&amp;gt; {
  const product = await form.getValue();

  setInitialValues({
    name: product.name,
    price: product.price,
    description: product.description,
  });
  await launchImageLibrary({}, (response) =&amp;gt; {
    // console.log(response.data);
    if (response.uri) {
      console.log('Photo Extension: \n');
      // console.log(response);
      setPhoto(response);
    }
  });
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If we don’t set initial values, launching the image library will reset the form.&lt;/p&gt;

&lt;p&gt;Don’t forget to add these imports as well.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import {launchImageLibrary} from 'react-native-image-picker'; 
import {Storage} from 'aws-amplify';


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can do a test run of the form. You should see something like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3g2gwrtxc0hrlkzzjpef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3g2gwrtxc0hrlkzzjpef.png"&gt;&lt;/a&gt;&lt;br&gt;AddProduct Screen
  &lt;/p&gt;

&lt;p&gt;Also, we should update our &lt;code&gt;handleSubmit&lt;/code&gt; function.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const handleSubmit = async () =&amp;gt; {
  try {
    const value = await form.getValue();
    console.log('value: ', value);
    const user = await Auth.currentAuthenticatedUser();
    if (photo) {
      const response = await fetch(photo.uri);

      const blob = await response.blob();
      console.log('FileName: \n');
      await Storage.put(photo.fileName, blob, {
        contentType: 'image/jpeg',
      });
    }
    const response = await API.graphql(
      graphqlOperation(createProduct, {
        input: {
          name: value.name,
          price: value.price.toFixed(2),
          description: value.description,
          userId: user.attributes.sub,
          userName: user.username,
          image: photo.fileName,
        },
      }),
    );
    console.log('Response :\n');
    console.log(response);
    navigation.navigate('Home');
  } catch (e) {
    console.log(e.message);
  }
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can upload an S3 Image into our bucket using &lt;code&gt;Storage.put&lt;/code&gt; method, provided by AWS Amplify Library. We need our file name (image key in S3 ) to access our file again. So we will store that in our database.&lt;/p&gt;

&lt;p&gt;Try uploading a new image. Submit the form. Wait until the image uploads. You should see a console.log like this.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    [Sat Jan 02 2021 01:58:21.981]  LOG      Response :

    [Sat Jan 02 2021 01:58:21.982]  LOG      {"data": {"createProduct": {"createdAt": "2021-01-01T20:28:22.382Z", "description": "About Sahan New Product", "id": "f3188508-5ee7-4af4-acf3-3c948f61d868", "image": "6ca2947e-766b-445e-b260-0041502e652a", "name": "Sahan New Product", "price": 200, "updatedAt": "2021-01-01T20:28:22.382Z", "userId": "7d5fa0a3-4d26-4354-8028-7cc597a69447", "userName": "sahan"}}}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  06. Retrieving AppSync Data
&lt;/h1&gt;

&lt;p&gt;Now, let’s show a Product List View on our home screen. For that, I have created two new components,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ProductCard Component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;directory: src/components/ProductCard.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React, {useEffect, useState} from 'react';
import {Text, StyleSheet, View} from 'react-native';
import {Card, Icon, Image} from 'react-native-elements';
import {Storage} from 'aws-amplify';

const ProductCard = ({
  productName,
  productOwner,
  productPrice,
  productImage,
}) =&amp;gt; {
  const [imageSource, setImageSource] = useState(null);
  const getImage = async () =&amp;gt; {
    try {
      const imageURL = await Storage.get(productImage);
      setImageSource({
        uri: imageURL,
      });
    } catch (e) {
      console.log(e);
    }
  };
  useEffect(() =&amp;gt; {
    getImage();
  }, []);
  return (
    &amp;lt;Card containerStyle={styles.cardContainer}&amp;gt;
      &amp;lt;Card.Title style={styles.cardTitle}&amp;gt;{productName}&amp;lt;/Card.Title&amp;gt;
      &amp;lt;Card.Divider /&amp;gt;
      {imageSource &amp;amp;&amp;amp; (
        &amp;lt;Image source={imageSource} style={styles.productImage} /&amp;gt;
      )}
      {!imageSource &amp;amp;&amp;amp; (
        &amp;lt;View style={styles.altView}&amp;gt;
          &amp;lt;Text&amp;gt;Product Image&amp;lt;/Text&amp;gt;
        &amp;lt;/View&amp;gt;
      )}
      &amp;lt;Text style={styles.productPrice}&amp;gt;{productPrice}$&amp;lt;/Text&amp;gt;
      &amp;lt;View style={styles.ownerTitle}&amp;gt;
        &amp;lt;Icon name="person-pin" /&amp;gt;
        &amp;lt;Text style={styles.productOwner}&amp;gt;{productOwner}&amp;lt;/Text&amp;gt;
      &amp;lt;/View&amp;gt;
    &amp;lt;/Card&amp;gt;
  );
};
const styles = StyleSheet.create({
  cardContainer: {
    marginBottom: 20,
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,

    elevation: 5,
  },
  productImage: {
    width: 200,
    height: 200,
    alignSelf: 'center',
  },
  productPrice: {
    marginTop: 10,
    marginBottom: 10,
    fontSize: 16,
    fontWeight: 'bold',
  },
  altView: {
    width: 200,
    height: 200,
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
  },
  cardTitle: {
    fontSize: 20,
  },
  productOwner: {
    fontSize: 16,
    fontWeight: 'bold',
    alignSelf: 'center',
  },
  ownerTitle: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'flex-end',
  },
});
export default ProductCard;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;ProductList Component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;directory: src/components/ProductList.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React from 'react';
import {View, Text, FlatList, StyleSheet, RefreshControl} from 'react-native';

import ProductCard from './ProductCard';

const ProductList = ({productList, refreshing, onRefresh}) =&amp;gt; {
  return (
    &amp;lt;View style={styles.productsView}&amp;gt;
      {productList &amp;amp;&amp;amp; (
        &amp;lt;FlatList
          style={styles.productList}
          refreshControl={
            &amp;lt;RefreshControl refreshing={refreshing} onRefresh={onRefresh} /&amp;gt;
          }
          keyExtractor={(item) =&amp;gt; item.id}
          data={productList}
          renderItem={({item}) =&amp;gt; {
            return (
              &amp;lt;ProductCard
                productName={item.name}
                productImage={item.image}
                productOwner={item.userName}
                productPrice={item.price}
              /&amp;gt;
            );
          }}
        /&amp;gt;
      )}
    &amp;lt;/View&amp;gt;
  );
};

const styles = StyleSheet.create({
  itemText: {
    fontSize: 15,
  },
  productText: {
    fontSize: 20,
    fontWeight: 'bold',
    alignSelf: 'center',
  },
  productsView: {
    padding: 0,
    margin: 0,
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  productList: {
    padding: 5,
    marginBottom: 20,
  },
});
export default ProductList;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, let’s use this ProductList Component in the Home Screen. Replace the current sample code with the following code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;directory: src/screens/home-screen.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React, {useEffect, useState} from 'react';
import {API} from 'aws-amplify';
import {SafeAreaView, StatusBar, TouchableOpacity} from 'react-native';

import {listProducts} from '../../graphql/queries';
import ProductList from '../components/ProductList';
const HomeScreen = (props) =&amp;gt; {
  const [productsList, setProducts] = useState([]);
  const [refreshing, setRefreshing] = useState(false);

  const fetchProducts = async () =&amp;gt; {
    try {
      const products = await API.graphql({query: listProducts});
      if (products.data.listProducts) {
        console.log('Products: \n');
        console.log(products);
        setProducts(products.data.listProducts.items);
      }
    } catch (e) {
      console.log(e.message);
    }
  };
  useEffect(() =&amp;gt; {
    fetchProducts();
  }, []);

  const onRefresh = async () =&amp;gt; {
    setRefreshing(true);
    await fetchProducts();
    setRefreshing(false);
  };
  return (
    &amp;lt;&amp;gt;
      &amp;lt;StatusBar barStyle="dark-content" /&amp;gt;
      &amp;lt;SafeAreaView&amp;gt;
        {productsList &amp;amp;&amp;amp; (
          &amp;lt;ProductList
            productList={productsList}
            refreshing={refreshing}
            onRefresh={onRefresh}
          /&amp;gt;
        )}
      &amp;lt;/SafeAreaView&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

export default HomeScreen;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the useEffect hook of our Home Screen, we are fetching all products. This time, we are running a GraphQL query &lt;code&gt;listProducts&lt;/code&gt;, which will be defined automatically in the &lt;code&gt;graphql/queries.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;We are passing those fetched products, into our ProductList Component. ProductList Component will render a ProductCard for each product.&lt;/p&gt;

&lt;p&gt;In PtoductCard Component, when we pass in the image filename to &lt;code&gt;Storage.get&lt;/code&gt; function, we will get the full image URL. &lt;/p&gt;

&lt;p&gt;Try running your app, you should now see your product list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwtxi2skgh2z54dy63mxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwtxi2skgh2z54dy63mxz.png"&gt;&lt;/a&gt;&lt;br&gt;Home Screen
  &lt;/p&gt;

&lt;h1&gt;
  
  
  07. Conclusion
&lt;/h1&gt;

&lt;p&gt;With that, we were able to complete all our functionalities successfully. How about letting users order products? I will save that for you to try on 😃.&lt;/p&gt;

&lt;p&gt;Congratulations on Completing the Tutorial! 🎉&lt;/p&gt;

&lt;p&gt;If we recap on what we have done,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We added Cognito Authentication to let users log-in or sign-up to our app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additionally, we included Navigation and Sign-out options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We created the AppSync GraphQL API, and we saved some product details in our Database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We created S3 Bucket to let users upload an image to each product.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At the Home Screen, we were able to show a product ListView to the user.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think now you have a good understanding of working with these different AWS resources in your ReactNative Apps.&lt;/p&gt;

&lt;p&gt;I hope you have completed all the steps without running into any issues. However, if you do, you can ask anything in the comments section below.&lt;/p&gt;

&lt;p&gt;Video Walkthrough related to this BlogPost:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Aws Amplify and React Native Crash Course&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/NqYQ0Muwf3c"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>amplify</category>
      <category>reactnative</category>
      <category>aws</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Complete Guide to Amplify and Next.js</title>
      <dc:creator>Sahan Amarsha</dc:creator>
      <pubDate>Wed, 30 Dec 2020 19:11:31 +0000</pubDate>
      <link>https://dev.to/dev_sahan/complete-guide-to-amplify-and-next-js-4318</link>
      <guid>https://dev.to/dev_sahan/complete-guide-to-amplify-and-next-js-4318</guid>
      <description>&lt;p&gt;Hello Everyone, this is the complete blog post for our Amplify + Next.js video series. So in this series, we will be building a fullstack web application with Amplify and Next.js.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Click &lt;a href="https://youtu.be/oihW1pms4A8" rel="noopener noreferrer"&gt;here&lt;/a&gt; to see the video walkthrough.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of Content
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Setting Up the Project&lt;/li&gt;
&lt;li&gt;Cognito Authentication&lt;/li&gt;
&lt;li&gt;AppSync API&lt;/li&gt;
&lt;li&gt;S3 Storage&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What We Will Build?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw653tutv8mmcd9vpziyp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw653tutv8mmcd9vpziyp.jpg"&gt;&lt;/a&gt;&lt;br&gt;App Preview
  &lt;/p&gt;

&lt;p&gt;We will build a simple profile app. Through this app, you can understand how to use AWS Cognito Authentication, AWS AppSync Backend API, and Amazon Simple Storage Service (S3).&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Next.js?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; is a React Static Site Generation Web Framework built by Vercel. Next.js introduced server-side React. Next.js has some cool features such as pre-rendering data-fetching methods, more on that later.&lt;/p&gt;

&lt;p&gt;Also, with Next.js you don’t have to create a router by yourself. You can simply create a new file. The route will be automatically generated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Amplify?
&lt;/h3&gt;

&lt;p&gt;Amplify is an AWS Framework that makes developing a full-stack application quite easy. The Amplify Framework provides the following services.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Amplify&lt;/strong&gt; &lt;a href="https://docs.amplify.aws/cli" rel="noopener noreferrer"&gt;&lt;strong&gt;CLI&lt;/strong&gt;&lt;/a&gt; — Configure all the services needed to power your backend through a simple command-line interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amplify&lt;/strong&gt; &lt;a href="https://docs.amplify.aws/lib/q/platform/js" rel="noopener noreferrer"&gt;&lt;strong&gt;Libraries&lt;/strong&gt;&lt;/a&gt; — Use case-centric client libraries to integrate your app code with a backend using declarative interfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amplify&lt;/strong&gt; &lt;a href="https://docs.amplify.aws/ui/q/framework/react" rel="noopener noreferrer"&gt;&lt;strong&gt;UI Components&lt;/strong&gt;&lt;/a&gt; — UI libraries for React, React Native, Angular, Ionic, and Vue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Amplify makes it easy to use AWS Services in a Full Stack App.&lt;/p&gt;

&lt;p&gt;First, let’s look at the AWS Architecture Diagram for our Application.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Architecture Diagram
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2c41h1lxdioix84kbdp9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2c41h1lxdioix84kbdp9.jpg"&gt;&lt;/a&gt;&lt;br&gt;AWS Architecture Diagram for our Profile App
  &lt;/p&gt;

&lt;p&gt;You will get the gist of these services as we go on with the project. Don’t worry Amplify makes it much easier to work with these different services.&lt;/p&gt;

&lt;p&gt;We will use an S3 Bucket to store our profile image. Amazon Cognito will handle Authentication. We will use AWS AppSync to develop our GraphQL API. Our data will be stored in Amazon DynamoDB, NoSQL Database.&lt;/p&gt;

&lt;p&gt;Ready to build the app? Let’s get started. 🛠️&lt;/p&gt;

&lt;p&gt;In order to avoid any disturbances in the future. Make sure you have the following prerequisites installed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; v10.x or later&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt; v5.x or later&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.amplify.aws/cli/start/install" rel="noopener noreferrer"&gt;Amplify CLI&lt;/a&gt; (v4.39.0 What I'm using in the Tutorial)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting Up the Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing and Configuring Amplify CLI
&lt;/h3&gt;

&lt;p&gt;Through this tutorial, we will work with AWS Amplify CLI. You can install it by running,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g @aws-amplify/cli@4.39.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you need to run &lt;code&gt;amplify configure&lt;/code&gt;. This will set up your Amplify CLI. There you will set up a new IAM User. You will finish setting up your IAM User, by providing the accessKeyId and secretAccessKey for your IAM user.&lt;/p&gt;

&lt;p&gt;If you are stuck at some point, you can refer to this original guideline on installing Amplify CLI, &lt;a href="https://docs.amplify.aws/cli/start/install" rel="noopener noreferrer"&gt;https://docs.amplify.aws/cli/start/install&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a New Next.js App
&lt;/h3&gt;

&lt;p&gt;Hope you have installed and configured Amplify CLI successfully.&lt;/p&gt;

&lt;p&gt;To start the proceedings, let’s start with setting up our Next.js Project. You will need to run these two commands from your project directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g create-next-app
npx create-next-app next-profileapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install &lt;code&gt;create-next-app&lt;/code&gt; npm package globally. The second command will create a new Next.js application in the directory &lt;code&gt;next-profileapp&lt;/code&gt;. Navigate into that directory, and open our newly created Next.js project in your preferred code editor. You should see a project structure similar to this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxvtu0cpn3a4ztup2m883.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxvtu0cpn3a4ztup2m883.jpg"&gt;&lt;/a&gt;&lt;br&gt;Next.js Project Structure
  &lt;/p&gt;

&lt;p&gt;You can test your project by running the command &lt;code&gt;npm run dev&lt;/code&gt; in your project directory. Your project will run at &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing Amplify Backend
&lt;/h3&gt;

&lt;p&gt;Now, we need to initialize Amplify for our project. Then we can add services one by one.&lt;/p&gt;

&lt;p&gt;In the project directory, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you will be prompted for the following information regarding the project you will initialize.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4n6tt4flgwjkryrwqg9o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4n6tt4flgwjkryrwqg9o.jpg"&gt;&lt;/a&gt;&lt;br&gt;Running amplify init
  &lt;/p&gt;

&lt;p&gt;Just accept the default. You should be good to go. For the AWS Profile, you can choose your default AWS Account, the one we have configured earlier.&lt;/p&gt;

&lt;p&gt;When you initialize your Amplify Project,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It creates a file called &lt;code&gt;aws-exports.js&lt;/code&gt; in the src directory. This file will store all the relevant information to identify the AWS resources/services that we are going to provision.&lt;/li&gt;
&lt;li&gt;It creates a directory called &lt;code&gt;amplify&lt;/code&gt;. This directory will be used to store the templates and configuration details of the services that we are going to use. In this directory, Amplify will hold our backend schema as well.&lt;/li&gt;
&lt;li&gt;You can use the command, &lt;code&gt;amplify console&lt;/code&gt; to access the cloud project’s AWS Amplify Console.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To complete setting up our Amplify Project, we need to configure amplify in a higher-order component. Adding the following lines of code in your App.js or inde.js file will do the job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "../styles/globals.css";
import awsExports from "../src/aws-exports";

Amplify.configure({...awsExports, ssr: true });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding Authentication
&lt;/h2&gt;

&lt;p&gt;Now, adding Authentication to your Next.js Application gets easier with Amplify. First, you need to include AWS Cognito Authentication Service to your Amplify Backend.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;amplify add auth&lt;/code&gt;, in your console. Submit the following information, when Configuring Authentication using the prompt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjgeqbs8znyzskixhwba7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjgeqbs8znyzskixhwba7.jpg"&gt;&lt;/a&gt;&lt;br&gt;Running amplify add auth
  &lt;/p&gt;

&lt;p&gt;Then, run &lt;code&gt;amplify push&lt;/code&gt;, to deploy your backend. Amplify will take care of the rest by creating your &lt;code&gt;Cognito Userpool&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can use &lt;code&gt;AmplifyAuthenticator&lt;/code&gt; Component to add login, signup functionalities in our Next.js Project. First, let’s install Amplify UI Components using npm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install aws-amplify @aws-amplify/ui-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to your &lt;code&gt;pages/_app.js&lt;/code&gt; file, configure Amplify, and wrap your return Component with &lt;code&gt;AmplifyAuthenticator&lt;/code&gt; like this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory: pages/_app.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Amplify } from "aws-amplify";
import { AmplifyAuthenticator } from "@aws-amplify/ui-react";
import awsExports from "../src/aws-exports";
import "../styles/globals.css";
Amplify.configure({ ...awsExports, ssr: true });
function MyApp({ Component, pageProps }) {
  return (
    &amp;lt;AmplifyAuthenticator&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/AmplifyAuthenticator&amp;gt;
  );
}
export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run your app. This login screen will show up. Try logging in as a new user. This will lead you to the home page. The user that we have created, will be saved in a Cognito User Pool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc1pf4nkh13722fddsn0j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc1pf4nkh13722fddsn0j.jpg"&gt;&lt;/a&gt;&lt;br&gt;Sign-in Screen by Amplify
  &lt;/p&gt;

&lt;p&gt;One issue though. Now we can’t log out. Let’s add a new ‘navigation component’, where we can add a ‘sign out button’.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a Navigation Bar
&lt;/h3&gt;

&lt;p&gt;Before that, let’s add Bootstrap. Since I want to use easy styling, I will be using Bootstrap throughout the tutorial.&lt;/p&gt;

&lt;p&gt;Run,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-bootstrap bootstrap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, add this import in your &lt;code&gt;pages/_app.js&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'bootstrap/dist/css/bootstrap.min.css';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a component directory. In that directory, add a new file called &lt;code&gt;Navbar.js&lt;/code&gt;. Copy and paste the following code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;directory: components/Navbar.js&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Link from "next/link";
import { Auth } from "aws-amplify";
import React from "react";
const Navbar = () =&amp;gt; {
  const signOutHandler = () =&amp;gt; {};
  return (
    &amp;lt;nav className="navbar w-100 navbar-expand navbar-dark bg-dark mb-4"&amp;gt;
      &amp;lt;div className="container"&amp;gt;
        &amp;lt;a className="navbar-brand" href="#"&amp;gt;
          Profile App
        &amp;lt;/a&amp;gt;
        &amp;lt;div className="collapse navbar-collapse"&amp;gt;
          &amp;lt;ul className="navbar-nav ml-auto"&amp;gt;
            &amp;lt;li className="nav-item"&amp;gt;
              &amp;lt;Link href="/"&amp;gt;
                &amp;lt;a className="nav-link"&amp;gt;Home&amp;lt;/a&amp;gt;
              &amp;lt;/Link&amp;gt;
            &amp;lt;/li&amp;gt;
            &amp;lt;li className="nav-item"&amp;gt;
              &amp;lt;Link href="/edit-user"&amp;gt;
                &amp;lt;a className="nav-link"&amp;gt;Edit User&amp;lt;/a&amp;gt;
              &amp;lt;/Link&amp;gt;
            &amp;lt;/li&amp;gt;
            &amp;lt;button
              className="btn btn-danger"
              type="button"
              onClick={signOutHandler}
            &amp;gt;
              Sign Out
            &amp;lt;/button&amp;gt;
          &amp;lt;/ul&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/nav&amp;gt;
  );
};
export default Navbar;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please notice that I have used a Sign-out Button in the Navbar. That button should trigger &lt;code&gt;Auth.signOut&lt;/code&gt; function provided by Amplify Library. This method will end the user session. Since we are using &lt;code&gt;AmplifyAuthenticator&lt;/code&gt; wrapper component, logged-out users will get automatically redirected to Sign-in Screen.&lt;/p&gt;

&lt;p&gt;Copy and paste the following code into &lt;code&gt;signOutHandler&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const signOutHandler = async () =&amp;gt; {
    try {
        await Auth.signOut();
    } catch (err) {
      console.log(err);
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, our Navbar is fully completed. Let’s use that Navigation bar on our home page.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;directory: pages/index.js&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import Head from "next/head";
import Navbar from "../components/Navbar";

export default function Home() {
  return (
    &amp;lt;div className="w-100 h-100 d-flex flex-column justify-content-start"&amp;gt;
      &amp;lt;Head&amp;gt;
        &amp;lt;title&amp;gt;Profile App&amp;lt;/title&amp;gt;
        &amp;lt;link rel="icon" href="/favicon.ico" /&amp;gt;
      &amp;lt;/Head&amp;gt;
      &amp;lt;Navbar /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I did clear the default page by &lt;code&gt;Next.js&lt;/code&gt;. Try signing out and logging back in. &lt;/p&gt;

&lt;p&gt;Now, we have successfully added Authentication into our Next.js Application. Congratulations on completing the first part of the tutorial! &lt;/p&gt;




&lt;p&gt;Now into the next part, we will complete our project by adding our AppSync API, and an S3 Bucket.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding AppSync API
&lt;/h2&gt;

&lt;p&gt;Let’s store some details on the user by adding an AppSync API to our Next.js application. Users can add first name, last name, and some description. The user should be able to add a profile image as well. We will add the profile image functionality in the next part.&lt;/p&gt;

&lt;p&gt;As I’ve said earlier, through &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;AppSync&lt;/a&gt;, we can build a &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL API&lt;/a&gt;. All the heavy lifting such as connecting and creating DynamoDB Tables, generating queries and mutations, will be done by AppSync.&lt;/p&gt;

&lt;h3&gt;
  
  
  Executing 'amplify add api'
&lt;/h3&gt;

&lt;p&gt;Using AppSync gets easier with Amplify. First, let’s add the AppSync API to our app.&lt;/p&gt;

&lt;p&gt;Run,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accept the default configurations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhnstlwzqw8dricxr9qg3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhnstlwzqw8dricxr9qg3.jpg"&gt;&lt;/a&gt;&lt;br&gt;Adding AppSync API
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Editing GraphQL Schema
&lt;/h3&gt;

&lt;p&gt;Navigate into &lt;code&gt;amplify/backend/api/schema.graphql&lt;/code&gt; file. This is where we will define our GraphQL schema. Let’s add a simple user schema. Copy and paste the following schema.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type User @model {
  id: ID!
  firstName: String
  lastName: String
  description: "String"
  image: String
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save the &lt;em&gt;&lt;strong&gt;schema.graphql&lt;/strong&gt;&lt;/em&gt; file. Run &lt;code&gt;amplify push&lt;/code&gt; to push your changes into Amplify Backend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ewk8c1c8sy2926x3zvq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ewk8c1c8sy2926x3zvq.jpg"&gt;&lt;/a&gt;&lt;br&gt;Running amplify push after adding AppSync API
  &lt;/p&gt;

&lt;p&gt;Now, our AppSync API has been created. Also, the AppSync Library automatically created queries, mutations for our GraphQL Schema. Run &lt;code&gt;amplify api console&lt;/code&gt; to view your AppSync API in AWS.&lt;/p&gt;

&lt;p&gt;You could play around with some GraphQL operations in this AWS AppSync Console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk7yc66nfr6xwyf0kdnkk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk7yc66nfr6xwyf0kdnkk.jpg"&gt;&lt;/a&gt;&lt;br&gt;AWS AppSync Console
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Edit User Page
&lt;/h3&gt;

&lt;p&gt;Let’s start interacting with our AppSync API.&lt;/p&gt;

&lt;p&gt;First, create a new page to edit user details. Create a new file called&lt;code&gt;edit-user.js&lt;/code&gt; in the pages directory. Copy and paste the following code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory: pages/edit-user.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from "react";
import { Form } from "react-bootstrap";
import { createUser, updateUser } from "../src/graphql/mutations";
import { API } from "@aws-amplify/api";
import { Auth } from  "@aws-amplify/auth";
import Navbar from "../components/Navbar";

const EditUser = () =&amp;gt; {
    const [firstName, setFirstName] = useState('');
    const [secondName, setSecondName] = useState('');
    const [description, setDescription] = useState('');
    const submitHandler = async (event) =&amp;gt; {
        event.preventDefault();
        // Save Details
    };
    return (
        &amp;lt;div className="d-flex flex-column justify-content-center w-100 h-100"&amp;gt;
            &amp;lt;Navbar /&amp;gt;
            &amp;lt;h1 className="align-self-center"&amp;gt;Edit User Details&amp;lt;/h1&amp;gt;
            &amp;lt;Form className="w-50 align-self-center"&amp;gt;
                &amp;lt;Form.Group className="mt-2" controlId="firstName"&amp;gt;
                    &amp;lt;Form.Label&amp;gt;First Name&amp;lt;/Form.Label&amp;gt;
                    &amp;lt;Form.Control
                        type="text"
                        value={firstName}
                        placeholder="Enter Your First Name"
                        onChange={(event) =&amp;gt; {
                            setFirstName(event.target.value);
                        }}
                    /&amp;gt;
                &amp;lt;/Form.Group&amp;gt;
                &amp;lt;Form.Group className="mt-2" controlId="secondName"&amp;gt;
                    &amp;lt;Form.Label&amp;gt;Second Name&amp;lt;/Form.Label&amp;gt;
                    &amp;lt;Form.Control
                        type="text"
                        value={secondName}
                        placeholder="Enter Your Second Name"
                        onChange={(event) =&amp;gt; {
                            setSecondName(event.target.value);
                        }}
                    /&amp;gt;
                &amp;lt;/Form.Group&amp;gt;
                &amp;lt;Form.Group className="mt-2" controlId="description"&amp;gt;
                    &amp;lt;Form.Label&amp;gt;Description&amp;lt;/Form.Label&amp;gt;
                    &amp;lt;Form.Control
                        as="textarea"
                        value={description}
                        rows={5}
                        placeholder="Enter Your Description"
                        onChange={(event) =&amp;gt; {
                            setDescription(event.target.value);
                        }}
                    /&amp;gt;
                &amp;lt;/Form.Group&amp;gt;
                &amp;lt;button
                    type="submit"
                    onClick={submitHandler}
                    className="btn btn-primary"
                &amp;gt;
                    Submit
                &amp;lt;/button&amp;gt;
            &amp;lt;/Form&amp;gt;
        &amp;lt;/div&amp;gt;
    );
};
export default EditUser;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple bootstrap form along with some state variables. Now you can navigate to ‘Edit User Page’ using the navbar. It should look something like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1p8j3zxqn8is7nodwn0z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1p8j3zxqn8is7nodwn0z.jpg"&gt;&lt;/a&gt;&lt;br&gt;Uploaded Profile Image Preview
  &lt;/p&gt;

&lt;p&gt;Now at the press of this submit button we need to save entered details. In order to do that, we need to call CreateUser GraphQL mutation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding 'submitHandler' Function
&lt;/h3&gt;

&lt;p&gt;Copy and paste the following code into &lt;code&gt;submitHandler&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const submitHandler = async (event) =&amp;gt; {    
    event.preventDefault();
    const currentUser = await Auth.currentAuthenticatedUser();
    try {
        const result = await API.graphql({
            query: createUser,
            variables: {
                input: {
                    id: currentUser.attributes.sub,
                    firstName: firstName,
                    lastName: secondName,
                    description: "description,"
                },
            },
        });
        console.log(result);
    } catch (err) {
        console.log(err);
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can test this. Fill in the inputs and press enter. You could try querying from our AppSync Console.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Auth.currentAuthenticatedUser()&lt;/code&gt; will do exactly what the name suggests. It will return details about the logged-in user. Cognito gives every user an attribute called &lt;code&gt;sub&lt;/code&gt;, a unique string value. We can use this value as the unique id in our User Table.&lt;/p&gt;

&lt;p&gt;Then I have called AppSync GraphQL API in order to perform ‘createUser’ mutation. This mutation will create a new record in our User Table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching Data in Pre-rendering Stage
&lt;/h3&gt;

&lt;p&gt;Now let’s examine a user scenario here. If I’m a new user I should be able to add my details to this App. If I have already added the details, I should be able to edit my information as well. Okay, let’s build this.&lt;/p&gt;

&lt;p&gt;I will use the &lt;code&gt;getServerSideProps&lt;/code&gt; method provided by Next.js. Through this method, we can fetch data on each request. Learn more about Next.js data fetching &lt;a href="https://nextjs.org/docs/basic-features/data-fetching" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Copy and paste the following code into &lt;code&gt;getServerSideProps&lt;/code&gt; method. Make sure to add the imports beforehand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { getUser } from "../src/graphql/queries";
import {withSSRContext} from "aws-amplify";

export async function getServerSideProps({ req, res }) {
  const { Auth, API } = withSSRContext({ req });
  try {
    const user = await Auth.currentAuthenticatedUser();
    const response = await API.graphql({
      query: getUser,
      variables: { id: user.attributes.sub },
    });

  if (response.data.getUser) {
      return {
        props: {
          mode: "EDIT",
          user: response.data.getUser,
          error: false,
        },
      };
    } else {
      return {
        props: {
          mode: "ADD",
          error: false,
        },
      };
    }
  } catch (err) {
    console.log(err);
    return {
      props: {
        error: true,
      },
    };
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This getStaticProps method will return an object with 3 fields.&lt;/p&gt;

&lt;p&gt;01. mode — &lt;em&gt;&lt;strong&gt;String&lt;/strong&gt;&lt;/em&gt; If the user is new, the mode is ‘ADD’, otherwise it is ‘EDIT.&lt;/p&gt;

&lt;p&gt;02. user — &lt;em&gt;&lt;strong&gt;JSON Object&lt;/strong&gt;&lt;/em&gt; Already added user details to preview initial values to the user, before editing.&lt;/p&gt;

&lt;p&gt;03. error — &lt;em&gt;&lt;strong&gt;Boolean&lt;/strong&gt;&lt;/em&gt; If something goes wrong, ‘true’. We will use this boolean to display something readable to the user.&lt;/p&gt;

&lt;p&gt;If you look closely, you should see that I’m querying user details in this method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const user = await Auth.currentAuthenticatedUser();
const response = await API.graphql({
  query: getUser,
  variables: { id: user.attributes.sub },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I have called AppSync GraphQL API with ‘getUser’ query. ‘getUser’ query will search through the DynamoDB to find a record with the given id. If there’s none response will return a null object.&lt;/p&gt;

&lt;p&gt;Now let’s use those pre-rendered data in our EditPage. We can set initial values and call ‘updateUser’ or ‘createUser’ mutation by considering our Mode.&lt;/p&gt;

&lt;p&gt;The final version of EditUser Page is like this. I have updated the &lt;code&gt;submitHandler&lt;/code&gt; function, and defined initial values for our state variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory: pages/edit-user.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, {useState} from "react";
import {Form} from "react-bootstrap";
import {getUser} from "../src/graphql/queries";
import {createUser, updateUser} from "../src/graphql/mutations";
import {withSSRContext} from "aws-amplify";
import {API} from "@aws-amplify/api";
import {Auth} from "@aws-amplify/auth";
import Navbar from "../components/Navbar";


export async function getServerSideProps({req, res}) {
    const {Auth, API} = withSSRContext({req});
    try {
        const user = await Auth.currentAuthenticatedUser();
        const response = await API.graphql({
            query: getUser,
            variables: {id: user.attributes.sub},
        });
        if (response.data.getUser) {
            return {
                props: {
                    mode: "EDIT",
                    user: response.data.getUser,
                    error: false,
                },
            };
        } else {
            return {
                props: {
                    mode: "ADD",
                    error: false,
                },
            };
        }
    } catch (err) {
        console.log(err);
        return {
            props: {
                error: true,
            },
        };
    }
}

const EditUser = ({user, error, mode}) =&amp;gt; {
    const [firstName, setFirstName] = useState(mode === 'EDIT' ? user.firstName : '');
    const [secondName, setSecondName] = useState(mode === 'EDIT' ? user.lastName : '');
    const [description, setDescription] = useState(mode === 'EDIT' ? user.description : '');
    const submitHandler = async (event) =&amp;gt; {
        event.preventDefault();
        const currentUser = await Auth.currentAuthenticatedUser();
        try {
            const result = await API.graphql({
                query: mode === 'EDIT' ? updateUser : createUser,
                variables: {
                    input: {
                        id: currentUser.attributes.sub,
                        firstName: firstName,
                        lastName: secondName,
                        description: "description,"
                    },
                },
            });
            console.log(result);
            window.location.href = "/";

        } catch (err) {
            console.log(err);
        }
    };

    if (error) {
        return (
            &amp;lt;div&amp;gt;
                &amp;lt;Navbar /&amp;gt;
                &amp;lt;h1&amp;gt;Something Went Wrong! Please Try Again Later.&amp;lt;/h1&amp;gt;
            &amp;lt;/div&amp;gt;
        );
    }
    return (
        &amp;lt;div className="d-flex flex-column justify-content-center w-100 h-100"&amp;gt;
            &amp;lt;Navbar/&amp;gt;
            &amp;lt;h1 className="align-self-center"&amp;gt;Edit User Details&amp;lt;/h1&amp;gt;
            &amp;lt;Form className="w-50 align-self-center"&amp;gt;
                &amp;lt;Form.Group className="mt-2" controlId="firstName"&amp;gt;
                    &amp;lt;Form.Label&amp;gt;First Name&amp;lt;/Form.Label&amp;gt;
                    &amp;lt;Form.Control
                        type="text"
                        value={firstName}
                        placeholder="Enter Your First Name"
                        onChange={(event) =&amp;gt; {
                            setFirstName(event.target.value);
                        }}
                    /&amp;gt;
                &amp;lt;/Form.Group&amp;gt;
                &amp;lt;Form.Group className="mt-2" controlId="secondName"&amp;gt;
                    &amp;lt;Form.Label&amp;gt;Second Name&amp;lt;/Form.Label&amp;gt;
                    &amp;lt;Form.Control
                        type="text"
                        value={secondName}
                        placeholder="Enter Your Second Name"
                        onChange={(event) =&amp;gt; {
                            setSecondName(event.target.value);
                        }}
                    /&amp;gt;
                &amp;lt;/Form.Group&amp;gt;
                &amp;lt;Form.Group className="mt-2" controlId="description"&amp;gt;
                    &amp;lt;Form.Label&amp;gt;Description&amp;lt;/Form.Label&amp;gt;
                    &amp;lt;Form.Control
                        as="textarea"
                        value={description}
                        rows={5}
                        placeholder="Enter Your Description"
                        onChange={(event) =&amp;gt; {
                            setDescription(event.target.value);
                        }}
                    /&amp;gt;
                &amp;lt;/Form.Group&amp;gt;
                &amp;lt;button
                    type="submit"
                    onClick={submitHandler}
                    className="btn btn-primary"
                &amp;gt;
                    Submit
                &amp;lt;/button&amp;gt;
            &amp;lt;/Form&amp;gt;
        &amp;lt;/div&amp;gt;
    );
};
export default EditUser;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s just some simple logic. If the user is in edit mode, we will have to trigger, GraphQL mutation ‘updateUser’. Otherwise, we will have to trigger, the GraphQL mutation ‘createUser’. Try submitting your details and come back to Edit Page again. You should see your values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fprxn2cs4du05gwq4l5x9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fprxn2cs4du05gwq4l5x9.jpg"&gt;&lt;/a&gt;&lt;br&gt;EditUser Page Showing Previously Entered Details
  &lt;/p&gt;

&lt;p&gt;Mine works, hope yours too.😃&lt;/p&gt;

&lt;p&gt;Now, by far we build a pretty cool application. How about letting users choose a profile image? We will need an Amazon S3 Bucket for that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Adding an S3 Storage
&lt;/h2&gt;

&lt;p&gt;You are into the third and final part of this tutorial.&lt;/p&gt;

&lt;p&gt;Through our app, the users can edit their details. Now, I want to add a profile image as well. We will need an S3 Bucket for that. Working with S3 really gets easier with Amplify. Let’s start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Executing 'amplify add storage'
&lt;/h3&gt;

&lt;p&gt;Run,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to create a new S3 Bucket. Accept the defaults in the prompt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0wzliljy242qdtv0ztvs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0wzliljy242qdtv0ztvs.jpg"&gt;&lt;/a&gt;&lt;br&gt;Running amplify add storage
  &lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;amplify push&lt;/code&gt; to deploy your changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating the Form
&lt;/h3&gt;

&lt;p&gt;Let’s add image uploading and previewing options into our form. I build a fancy ImageUploader component with an image preview. Make sure to add that under the components directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory: components/ImageUploader.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";

const ImageUploader = ({imageUploadHandler, image}) =&amp;gt; {
    return (
        &amp;lt;div&amp;gt;
            &amp;lt;input className="btn-primary" type="file" onChange={imageUploadHandler}/&amp;gt;
            &amp;lt;div className="image-container"&amp;gt;
                {image &amp;amp;&amp;amp; &amp;lt;img className="uploaded-image" alt='Uploaded Image' src={URL.createObjectURL(image)}/&amp;gt;}
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
);
}

export default ImageUploader;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add these CSS styles into your &lt;code&gt;styles/global.css&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify-s3-image {
  --height: 300px;
  --width: 300px;
}
.image-container {
  box-shadow: -7px 20px 41px 0 rgba(0,0,0,0.41);
  width: 300px;
  height: 300px;
  max-width: 400px;
  max-height: 400px;
  position: relative;
  display: inline-block;
  overflow: hidden;
  margin: 0;
}
.uploaded-image {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  height: 100%;
  width: 100%;
  transform: translate(-50%, -50%);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use AmplifyS3Image Component to preview already uploaded profile images. In order to use these two components, we will make these changes in our EditUser.js file.&lt;/p&gt;

&lt;p&gt;We will add these two components inside our form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Form className="w-50 align-self-center"&amp;gt;

  {editImage &amp;amp;&amp;amp; (
    &amp;lt;ImageUploader
      imageUploadHandler={imageUploadHandler}
      image={userImage}
    /&amp;gt;
  )}
  {!editImage &amp;amp;&amp;amp; (
    &amp;lt;div&amp;gt;
      &amp;lt;button
        type="button"
        className="btn m-2 btn-outline-primary"
        onClick={() =&amp;gt; {
          setEditImage(true);
        }}
      &amp;gt;
        Edit Image
      &amp;lt;/button&amp;gt;
      &amp;lt;AmplifyS3Image imgKey={user.image} /&amp;gt;
    &amp;lt;/div&amp;gt;
  )}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AmplifyS3Image&lt;/code&gt; component is perfect for displaying S3 images. If you provide the relevant image key (S3 File Name), it displays your S3 Image. Declare these two state variables along with the new &lt;code&gt;imageUploadHandler&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [editImage, setEditImage] = useState(!user.image);
const [userImage, setUserImage] = useState(null);

const imageUploadHandler = (event) =&amp;gt; {
  setUserImage(event.target.files[0]);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t forget to add these imports as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Storage } from "@aws-amplify/storage";
import { AmplifyS3Image } from "@aws-amplify/ui-react";
import { v4 as uuid } from "uuid";
import ImageUploader from "../components/ImageUploader";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see something like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fst7hb83sjjrz6vnck6eg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fst7hb83sjjrz6vnck6eg.jpg"&gt;&lt;/a&gt;&lt;br&gt;Form with ImageUploader
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Updating the 'submitHandler' Function
&lt;/h3&gt;

&lt;p&gt;Now let’s update the &lt;code&gt;submitHandler&lt;/code&gt; method. Replace the current code with the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const submitHandler = async (event) =&amp;gt; {
    event.preventDefault();
    const currentUser = await Auth.currentAuthenticatedUser();
    try {
        let key = null;
        if(userImage) {
            key = `${uuid()}${user.firstName}`;

            if(user.image) {
                await Storage.remove(user.image);
            }
            await Storage.put(key, userImage, {
                contentType: userImage.type,
            });
        }
        const result = await API.graphql({
            query: mode === 'EDIT' ? updateUser : createUser,
            variables: {
                input: {
                    id: currentUser.attributes.sub,
                    image: userImage ? key : user.image,
                    firstName: firstName,
                    lastName: secondName,
                    description: description,
                },
            },
        });
        console.log(result);
        window.location.href = "/";

    } catch (err) {
        console.log(err);
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can upload an S3 Image into our bucket using &lt;code&gt;Storage.put&lt;/code&gt; method, provided by AWS Amplify Library. As I’ve mentioned earlier, we need our file name (image key in S3 ) to access our file again. So we will store that in our database.&lt;/p&gt;

&lt;p&gt;If the user is replacing the profile image. We need to remove the existing one. We can remove an S3 file by using &lt;code&gt;Storage.remove&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Try uploading a new image. Submit the form. Wait until the image uploads. When you navigate back to EditUser Page, you should see your profile image like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftp8j8m1a96u7zbnjamii.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftp8j8m1a96u7zbnjamii.jpg"&gt;&lt;/a&gt;&lt;br&gt;Uploaded Profile Image Preview
  &lt;/p&gt;

&lt;p&gt;Congratulations on completing the tutorial! 🎉&lt;/p&gt;

&lt;p&gt;I think now, you have a good understanding of how to work with Amplify in your Next.js Application. After all, we did work with AppSync API, Cognito Authentication, and AWS S3.&lt;/p&gt;

&lt;p&gt;I hope you have completed all the steps without running into any issues. However, if you do, you can ask me from the comments section below.&lt;/p&gt;

&lt;p&gt;Video Walkthrough related to this BlogPost:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 1: Setting Up the Project and Adding Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/oihW1pms4A8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2: Adding AppSync API and S3 Storage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hbx1AlbiuzE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>amplify</category>
      <category>nextjs</category>
      <category>aws</category>
      <category>react</category>
    </item>
  </channel>
</rss>
