DEV Community

Cover image for Complete Guide to AWS Amplify and React Native
Sahan Amarsha
Sahan Amarsha

Posted on

Complete Guide to AWS Amplify and React Native

Let’s Build an E-commerce App with ReactNative and Amplify

Click here to see the video walkthrough.

Table of Content

  1. Introduction

  2. Setting Up the Project

  3. Adding Cognito Authentication

  4. Adding AppSync API

  5. Adding S3 Storage

  6. Retrieving AppSync Data

  7. Conclusion

01. Introduction

Hello! & 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.

Here is a quick demo,


Different Screens in Mobile App

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.

Architecture Diagram

The following diagram demonstrates our AWS Architecture Diagram.


AWS Architecture Diagram for Mobile App

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.

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 S3 Bucket. Product details will be saved in Amazon DynamoDB, a NoSQL database provided by AWS. To talk with that Database, we will use a GraphQL API provided by AWS AppSync. Amazon Cognito will handle authentication.

Ready to build the app? Let’s get started. 👷🏽‍♂️🧰

Prerequisites

To avoid any disturbances in the future, make sure you have the following prerequisites installed.

02. Setting Up the Project

Installing and Configuring Amplify CLI

Through this tutorial, we will work with AWS Amplify CLI. You can install it by running,



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


Enter fullscreen mode Exit fullscreen mode

Then you need to run amplify configure. 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.

If you are stuck at some point, you can refer to this original guideline on installing Amplify CLI, https://docs.amplify.aws/cli/start/install

Creating a New ReactNative Application

Hope you have installed and configured Amplify CLI.

To work with ReactNative, you will have to set up the Android development environment. You can refer to this original guide, https://reactnative.dev/docs/environment-setup

Let’s create a new React Native app called AmplifyShop.



npx react-native init amplify_shop


Enter fullscreen mode Exit fullscreen mode

If you have already installed react-native-cli, you can use that instead of npx.

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.



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


Enter fullscreen mode Exit fullscreen mode

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.

Initializing Amplify Backend

Let’s initialize Amplify for our project. Then we can add services one by one.

In the project directory, run



amplify init


Enter fullscreen mode Exit fullscreen mode

Then you will be prompted for the following information regarding the project you initialize.


Running 'amplify init'

When you initialize your Amplify Project,

  • It creates a file called aws-exports.js in the src directory. This file will store all the relevant information to identify the AWS resources/services that will allocate in the future.

  • It creates a directory called amplify. 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.

  • It creates a Cloud Project. That project can be viewed using the amplify console command.

Next, we need to install all the necessary dependencies by running the following command.



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


Enter fullscreen mode Exit fullscreen mode

You will also need to install the pod dependencies for iOS.



npx pod-install


Enter fullscreen mode Exit fullscreen mode

Configuring Amplify Backend

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 index.js file will do the job.



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

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


Enter fullscreen mode Exit fullscreen mode

That completes setting up the project. Now let’s add those services one by one.

03. Adding Cognito Authentication

Now, adding Authentication to your React Native App never gets easier than Amplify.

Adding Sign-up and Log-in

Run amplify add auth in your project directory. Submit the following information when configuring Authentication.


Running 'amplify add auth'

Then, run amplify push, to deploy your backend changes. Amplify will take care of the rest by creating your Cognito Userpool.

The authentication UI component, provided by Amplify Framework, will provide the entire authentication flow.

In the App.js file,

  • Import withAuthenticator component


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


Enter fullscreen mode Exit fullscreen mode
  • Wrap the main component with withAuthenticator component.


export default withAuthenticator(App)


Enter fullscreen mode Exit fullscreen mode

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.


Sign-in Screen by Amplify

Before Adding AppSync API, let’s add navigation to our App.

Adding ReactNative Navigation

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.

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

Copy and paste the following sample code. Do change the function name (‘HomeScreen’ and ‘AddProductScreen’) and the title according to the page.

directory: src/screens/ home.js, add-product-screen.js



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

const HomeScreen = (props) => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <Text>Home</Text>
      </SafeAreaView>
    </>
  );
};

export default HomeScreen;


Enter fullscreen mode Exit fullscreen mode

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.



npm install @react-navigation/native


Enter fullscreen mode Exit fullscreen mode

Install all the additional third-party dependencies as well.



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


Enter fullscreen mode Exit fullscreen mode

From React Native 0.60 and higher, linking is automatic. So you don’t need to run react-native link.

If you’re on a Mac and developing for iOS, you need to install the pods (via Cocoapods) to complete the linking.



npx pod-install ios


Enter fullscreen mode Exit fullscreen mode

To finish installing React Native Navigation, add the following import in your App.js or index.js file.



import 'react-native-gesture-handler';


Enter fullscreen mode Exit fullscreen mode

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



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


Enter fullscreen mode Exit fullscreen mode

In order to view fontawesome icons, we need to add the following line into android/app/build.gradle file.



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


Enter fullscreen mode Exit fullscreen mode

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

directory: App.js



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

export default withAuthenticator(App);


Enter fullscreen mode Exit fullscreen mode

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

We can use that options 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.

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.

Adding Sign-Out Option

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

Do paste in the following code along with the import.



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


Enter fullscreen mode Exit fullscreen mode

Sign-out button will trigger, Auth.signOut() 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.

So, that’s it for Navigation. Learn more about React Native Navigation here. In the end, the result should be something like this.


After Adding Navigation

04. Adding AppSync API

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.

Executing ‘amplify add api’

As I’ve said earlier, through AppSync, we can build a GraphQL API. All the heavy lifting, such as connecting and creating DynamoDB tables, generation queries, and mutations, will be done by AppSync.

Let’s started by provisioning an AppSync API for our Amplify Backend. Execute,



amplify add api


Enter fullscreen mode Exit fullscreen mode

and you will be prompted for the following information.


Running 'amplify add api'

Just accept the defaults.

Editing GraphQL Schema

Let’s edit our schema. You will find our schema.graphql file in amplify/backend/api/schema.graphql directory. Copy and paste the following schema.



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
}


Enter fullscreen mode Exit fullscreen mode

Save the file. Follow with an amplify push to deploy your changes into AWS Cloud.


Running 'amplify push' after adding AppSync API

Now, our AppSync API has been created. Also, the AppSync Library automatically created queries, mutations for our GraphQL Schema. Run amplify api console to view your AppSync API in AWS.

You could play around with some GraphQL operations in this AWS AppSync Console.


AWS AppSync Console

Adding AddProduct Screen

Let’s start interacting with our AppSync API.

Before that, I want to add an extra package that will help in creating a React Native Form. With the tcomb-form-native package, you can quickly create a form on the fly. So, let’s install it using npm.



npm install tcomb-form-native


Enter fullscreen mode Exit fullscreen mode

Copy and paste the following code into our add-product-screen.js file.

directory: src/screens/add-product-screen.js



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}) => {
  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 () => {
    // Saving product details
  };
return (
    <>
      <SafeAreaView style={styles.addProductView}>
        <ScrollView>
          <Form
            ref={(c) => setForm(c)}
            value={initialValues}
            type={User}
            options={options}
          />
          <Button title="Save" onPress={handleSubmit} />
        </ScrollView>
      </SafeAreaView>
    </>
  );
};
const styles = StyleSheet.create({
  addProductView: {
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    paddingTop: 15,
    height: 'auto',
  },
});
export default AddProductScreen;


Enter fullscreen mode Exit fullscreen mode

Try running your app, you should see a form just like this.

Let’s inspect our code.

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

In our handleSubmit function, we are saving entered details in the database. Paste in the following code inside our handleSubmit function. Don’t forget the imports.



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);
    }


Enter fullscreen mode Exit fullscreen mode

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

The createProduct mutation was generated automatically. Here we are referring to that mutation, which was defined in graphql/mutations.js file.

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.

05. Adding S3 Storage

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.

Before that, install the React Native image picker library.



npm install react-native-image-picker


Enter fullscreen mode Exit fullscreen mode

RN >= 0.60
cd ios && pod install

RN < 0.60
react-native link react-native-image-picker

For now, this image picker library will support only 21 or newer SDK Versions. So edit minSDK version in android/build.gradle file.

buildToolsVersion = "29.0.2"
minSdkVersion = 21
compileSdkVersion = 29
targetSdkVersion = 29

Executing ‘amplify add storage’

Run,



amplify add storage


Enter fullscreen mode Exit fullscreen mode

to create a new S3 Bucket. Accept the defaults in the prompt.


Running 'amplify add storage'

Run amplify push, to deploy your changes.

Updating the Form

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 components directory in the src folder.

directory: src/components/ImageUploader.js



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

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

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

export default ImageUploader;


Enter fullscreen mode Exit fullscreen mode

In order to use this image uploading option, we will make the following changes in our add-product-screen.js file.

We will add the extra ImageUploader Component inside our ScrollView Component.



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


Enter fullscreen mode Exit fullscreen mode

Declare this state variable along with the new handleChoosePhoto function.



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

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


Enter fullscreen mode Exit fullscreen mode

If we don’t set initial values, launching the image library will reset the form.

Don’t forget to add these imports as well.



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


Enter fullscreen mode Exit fullscreen mode

You can do a test run of the form. You should see something like this.


AddProduct Screen

Also, we should update our handleSubmit function.



const handleSubmit = async () => {
  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);
  }
};


Enter fullscreen mode Exit fullscreen mode

We can upload an S3 Image into our bucket using Storage.put 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.

Try uploading a new image. Submit the form. Wait until the image uploads. You should see a console.log like this.



    [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"}}}


Enter fullscreen mode Exit fullscreen mode

06. Retrieving AppSync Data

Now, let’s show a Product List View on our home screen. For that, I have created two new components,

  • ProductCard Component

directory: src/components/ProductCard.js



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,
}) => {
  const [imageSource, setImageSource] = useState(null);
  const getImage = async () => {
    try {
      const imageURL = await Storage.get(productImage);
      setImageSource({
        uri: imageURL,
      });
    } catch (e) {
      console.log(e);
    }
  };
  useEffect(() => {
    getImage();
  }, []);
  return (
    <Card containerStyle={styles.cardContainer}>
      <Card.Title style={styles.cardTitle}>{productName}</Card.Title>
      <Card.Divider />
      {imageSource && (
        <Image source={imageSource} style={styles.productImage} />
      )}
      {!imageSource && (
        <View style={styles.altView}>
          <Text>Product Image</Text>
        </View>
      )}
      <Text style={styles.productPrice}>{productPrice}$</Text>
      <View style={styles.ownerTitle}>
        <Icon name="person-pin" />
        <Text style={styles.productOwner}>{productOwner}</Text>
      </View>
    </Card>
  );
};
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;


Enter fullscreen mode Exit fullscreen mode
  • ProductList Component

directory: src/components/ProductList.js



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

import ProductCard from './ProductCard';

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

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;


Enter fullscreen mode Exit fullscreen mode

Now, let’s use this ProductList Component in the Home Screen. Replace the current sample code with the following code.

directory: src/screens/home-screen.js



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) => {
  const [productsList, setProducts] = useState([]);
  const [refreshing, setRefreshing] = useState(false);

  const fetchProducts = async () => {
    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(() => {
    fetchProducts();
  }, []);

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

export default HomeScreen;


Enter fullscreen mode Exit fullscreen mode

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

We are passing those fetched products, into our ProductList Component. ProductList Component will render a ProductCard for each product.

In PtoductCard Component, when we pass in the image filename to Storage.get function, we will get the full image URL.

Try running your app, you should now see your product list.


Home Screen

07. Conclusion

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 😃.

Congratulations on Completing the Tutorial! 🎉

If we recap on what we have done,

  1. We added Cognito Authentication to let users log-in or sign-up to our app.

  2. Additionally, we included Navigation and Sign-out options.

  3. We created the AppSync GraphQL API, and we saved some product details in our Database.

  4. We created S3 Bucket to let users upload an image to each product.

  5. At the Home Screen, we were able to show a product ListView to the user.

I think now you have a good understanding of working with these different AWS resources in your ReactNative Apps.

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.

Video Walkthrough related to this BlogPost:

Aws Amplify and React Native Crash Course

Top comments (2)

Collapse
 
yogeshkun profile image
yogesh kunkawlekar

Sir, I am getting error

ERROR TypeError: Cannot read property 'configure' of undefined, js engine: hermes
LOG Running "locationalert" with {"rootTag":11}

ERROR Invariant Violation: "locationalert" has not been registered. This can happen if:

  • Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
  • A module failed to load due to an error and AppRegistry.registerComponent wasn't called., js engine: hermes

This is error is after amplify add auth, when I start my react-native app

Collapse
 
adtiyathakkar profile image
adtiyathakkar

Hi, it was excellent article. my AWS auth login UX has been loaded but from login page when i am clicking on signUP i am getting Invariant Violation: Picker has been removed from React Native. It can now be installed and imported from '@react-native-picker/picker' instead of 'react-native' this error. can you please help me out. i am trying with fresh project