Building Serverless Mobile Applications with React Native & AWS

Ayush Kumar srivastava
12 min readJun 8, 2021

In this post, we’ll look at how to build fully serverless & backendless mobile applications with AWS Amplify & React Native that include features like authentication, analytics, a managed data layer, storage & push notifications.

Update: This article currently uses the AWS Mobile CLI. The AWS Mobile CLI will be deprecated in the future, the preferred way is to use the Amplify CLI. The commands are similar as well as the configurations. See the documentation here for any questions.

When building a real-world mobile application there are a ton of essential basic requirements.

You need to have a way to authenticate users, you want to track user engagement & usage, & you probably want to be able to send push notifications and maybe base these messages on events or user behavior. Then you have to manage your application data and are probably dealing with multiple REST endpoints. You’re also usually dealing with media such as images & videos and you hopefully want to be able to handle offline use cases so that the app continues to work whether or not they are online.

More and more developers & companies are adopting and taking advantage of managed services in order to lessen their dependence on building & maintaining their own infrastructure and having to create this functionality from scratch, lowering the cost and decreasing the complexity of their back end development infrastructure in the process.

It’s now even possible for a single developer without a lot of traditional back end experience to be able to build and ship a fully featured application by taking advantage of these managed backend services, bringing about what I consider the next revolution of architecture that will dominate in the future, backend-less application development.

Some of the more popular existing use cases that come to mind are push notification services, authentication providers, & analytics services. There are now also services like AWS AppSync that offer completely managed data layers so you can also offload the complexity & work of building & maintaining your backend & API to a managed service with a single GraphQL endpoint.

In this post, we’ll look at how to leverage the AWS Mobile CLI to quickly spin up these types of services & add new this new functionality to your React Native application using the AWS Amplify JavaScript SDK.

The AWS Amplify JavaScript SDK was created to provide a unified API across many of AWS’ services & managed services. There is first class support for JavaScript frameworks like React Native, React, & Angular.

The projects we will create in this post will be created from the AWS Mobile CLI but will also be accessible from within the AWS Mobile Hub console as we’ll see in just a moment.

We’ll touch on how to not only create these services through the AWS Mobile CLI but also show how to integrate them into a React Native application using AWS Amplify.

Getting Started

Creating the React Native App

First we’ll create a new React Native project using either the React Native CLI or the Create React Native App CLI:

react-native init ServerlessProject

Next, we’ll change into the directory:

cd ServerlessProject

Installing the AWS Mobile CLI

The AWS Mobile CLI offers a way to quickly & easily spin up new AWS Mobile Hub projects from the command line.

To get started we’ll now need to install & configure the AWS Mobile CLI if you don’t already have it installed:

npm i -g awsmobile-cli
awsmobile configure

If you’re not sure how to work with AWS IAM roles, check out this video walking through how to configure the AWS Mobile CLI from end to end in just a couple of minutes.

Once the CLI is installed & configured, we need to go ahead and create a new AWS Mobile Project. From within the new React Native project root directory create a new AWS Mobile project:

awsmobile init

Now, answer the default to all questions from awsmobile init.

This will also install a couple of local dependencies to our project. You should now see aws-amplify & aws-amplify-react-native in your package.json.

Finally, we need to link anaws-amplify native dependency:

react-native link amazon-cognito-identity-js

We now have a new Mobile Hub project created in our AWS dashboard. You can view the project & configuration at anytime by running awsmobile console from the root of the React Native directory.

Configuring the React Native app with your new AWS Mobile Hub project.

Now that the Mobile Hub project has been created & the dependencies are all installed, we can configure the React Native project to recognize our configuration.

In index.js, let’s add the following lines of code:

import { AppRegistry } from 'react-native';
import App from './App';import Amplify from 'aws-amplify' // NEW
import config from './aws-exports' // NEW
Amplify.configure(config
) // NEWAppRegistry.registerComponent('ServerlessProject', () => App);

User Sign Up & Sign In

The first thing we’ll do is look at how we can add user sign up & sign in.

To do so we’ll need to enable it in our Mobile Hub Project.

awsmobile user-signin enableawsmobile push

Now user signup and signin is enabled through Amazon Cognito and we can immediately start signing users up and in.

If we look at the docs we’ll notice that there are two distinct ways to do this:

  1. We can use the React components & higher order components for preconfigured functionality & UI
  2. We can write this functionality from scratch using the Auth class which contains methods like Auth.signUp() & Auth.signIn()

React Native Components

Let’s first check out how to use the withAuthenticator HOC from aws-amplify-react-native.

In App.js, below the React Native imports let’s import the withAuthenticator HOC:

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

Next, instead of having the default export on the class we’ll use the HOC as the default export:

class App extends Component {
// all of this code stays the same
}export default withAuthenticator(App)

Next, run the app:

react-native run-ios
// or
react-native run-android
Configuring the React Native app with your new AWS Mobile Hub project.

Now that the Mobile Hub project has been created & the dependencies are all installed, we can configure the React Native project to recognize our configuration.

In index.js, let’s add the following lines of code:

import { AppRegistry } from 'react-native';
import App from './App';import Amplify from 'aws-amplify' // NEW
import config from './aws-exports' // NEW
Amplify.configure(config
) // NEWAppRegistry.registerComponent('ServerlessProject', () => App);

User Sign Up & Sign In

The first thing we’ll do is look at how we can add user sign up & sign in.

To do so we’ll need to enable it in our Mobile Hub Project.

awsmobile user-signin enableawsmobile push

Now user signup and signin is enabled through Amazon Cognito and we can immediately start signing users up and in.

If we look at the docs we’ll notice that there are two distinct ways to do this:

  1. We can use the React components & higher order components for preconfigured functionality & UI
  2. We can write this functionality from scratch using the Auth class which contains methods like Auth.signUp() & Auth.signIn()

React Native Components

Let’s first check out how to use the withAuthenticator HOC from aws-amplify-react-native.

In App.js, below the React Native imports let’s import the withAuthenticator HOC:

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

Next, instead of having the default export on the class we’ll use the HOC as the default export:

class App extends Component {
// all of this code stays the same
}export default withAuthenticator(App)

Next, run the app:

react-native run-ios
// or
react-native run-android

Now, we have a completely functioning sign up / sign in process in front of our main app.

To achieve similar functionality you can also use the <Authenticator /> component to wrap whatever main component you would like to authenticate:

<Authenticator>
<App />
</Authenticator>

In the wrapped component (App), you will have access to a prop called authState that you can use to conditionally render. authState will have values of signIn, signUp, & signedIn among others to properly identify the current authentication state.

Auth Class

We can also use the Auth class to authenticate users.

import { Auth } from 'aws-amplify'// in your component
Auth.signIn('myusername', 'mYC0MP13xP@55w0r8')

Auth has over 30 methods including signUp, confirmSignUp, signIn, confirmSignIn, &changePassword. You can also do things like change MFA type to TOTP & update user attributes!

When you sign in using Auth.signIn, the session data will be persisted and can be accessed at any time using the Auth.currentauthenticateduser method.

Once you have signed in new users, you can view the configuration in AWS Mobile Hub or go to https://console.aws.amazon.com/cognito and view the users & Amazon cognito configuration for the app.

To view your current project configurations you can always type in:

awsmobile console

Then click on Resources in the top right corner, and click on the resource you would like to viewAnalytics

Analytics events can be tracked using the Analytics class.

Analytics.record('sale price section viewed')

We can also call events with more detailed attributes:

Analytics.record('sale price item viewed', { itemName: 'USA Socks' , timestamp: 'June 13 2018 4:03pm ET' })

To view the analytics data we can go to the AWS Mobile Hub project in the console, again clicking on Resources in the top right corner, and choosing Pinpoint and clicking on your service.

awsmobile console
// Click on Resources, then Pinpoint

Pinpoint dashboard

Storage

Amplify has a Storage class that allows easy interop with React Native making the storage and access of media like images & media much easier, working seamlessly with Amazon S3.

We can enable storage in the AWS Mobile Hub project from the command line:

awsmobile user-files enable
awsmobile push

Now we can use the Storage class in our app:

import { Storage } from 'aws-amplify'

We can use storage to place items into storage:

Storage.put('test.txt', 'Hello')
.then (result => console.log(result))
.catch(err => console.log(err));

And read them from storage:

Storage.get('test.txt')
.then(result => console.log(result))
.catch(err => console.log(err));

We can also fairly easily place media to storage (assuming we’ve installed & configured react-native-fetch-blob).

import RNFetchBlob from 'react-native-fetch-blob';readFile(filePath) {
return RNFetchBlob.fs.readFile(filePath, 'base64').then(data => new Buffer(data, 'base64'));
}
readFile(imagePath).then(buffer => {
Storage.put('MYKEY', buffer, {
contentType: 'image/jpeg'
})
}).catch(e => {
console.log(e);
});

To view the S3 bucket, we can run awsmobile console from the command line, click on Resources, and under Amazon S3 Buckets click on the userfiles bucket.

Lambda Functions

When you hear “Serverless” you may typically think of a Lambda function. We can set one of these up manually and connect it with our existing AWS Amplify resources, or we can use the AWS Mobile CLI to set this up for us. Let’s continue using the CLI to create the new Lambda function.

To add a Lambda function as well as have it configured for you off the bat with some basic configuration, run the following command:

awsmobile cloud-api enable

You can also pass in the --prompt flag if you would like to specify the configuration around your lambda function (awsmobile cloud-api enable --prompt), but for our case we’ll just stick with the defaults.

awsmobile cloud-api enable will automatically create an API in API Gateway as well as a Lambda function and associate the two together.

Now, we can look in our project in awsmobilejs/backend/cloud-api to see some new configuration. Here, we see we have another new folder called sampleLambda holding a sample Lambda function that was deployed for us.

The Lambda function that was created for us is using the AWS Serverless Express package to spin up an express server with some preconfigured endpoints. These endpoints can be updated in our local code and pushed up to the server using the awsmobile push command as we’ll see in a second. We can also add new endpoints by configuring our local code as well as the cloud logic configuration in our AWS Mobile Hub project in the console.

Let’s update the app.get method on the /items path in awsmobilejs/backend/cloud-api/sampleLambda:

/// rest of file omittedapp.get('/items', function(req, res) {
res.json({
body: "HELLO WORLD"
});
});

Next we need to push this new API and configuration to our AWS Mobile Hub project:

awsmobile push

Now, we’ll open the AWS Mobile Hub console to get the API name:

awsmobile console

Click on Cloud Logic, and copy the API Name (Mine is sampleCloudApi).

Now we can test out the Lambda function. In App.js, create a new componentDidMount lifecycle method:

async componentDidMount() {
const data = await API.get('sampleCloudApi', '/items')
console.log('data: ', data)
}

Managed API & Data Layer

AWS Amplify offers a GraphQL client that works with any GraphQL API. In our case, we’ll be looking at AWS AppSync which is a fully managed GraphQL service.

With AWS AppSync, you can have a GraphQL API that interacts with any data source you would like. There are built in data sources like Amazon DynamoDB, AWS Lambda Function or Amazon Elasticsearch, and with a Lambda function you can access any service or database you would like seamlessly through the single API layer that is GraphQL in the form of your AppSync API.

There are a couple of GraphQL clients that work with AWS AppSync. AWS Amplify has an API category that works seamlessly with any GraphQL API including AWS AppSync.

We can enable AWS AppSync from the AWS Mobile CLI, but doing so will create an autogenerated schema & datasource. Instead, we’ll visit the console to create and manually configure a custom API & configuration from the console.

In this example, we’ll look at a basic Todo app.

To get started, visit https://console.aws.amazon.com/appsync and click on CREATE API.

From here, give the API a name, choose Custom Schema, then click Create.

Now the API has been created and we’re given some information including the API URL & API Key.

Click Schema in the left menu and create a basic schema with a type & a query:

type Todo {
id: ID!
name: String!
completed: Boolean!
}type Query {
fetchTodos(id: ID!): Todo
}

Click Save then click the Create Resources button 👇.

Choose defaults & click Create at the bottom of the screen.

Create Resources will automatically provision a DynamoDB database, additional GraphQL Schema for multiple operations including queries, mutations, & subscriptions, & resolvers that tie the GraphQL operations to the data source.

Next, click Queries in the left menu to test out a mutation & query to make sure everything is working properly:

mutation add {
createTodo(input: {
name: "Get groceries"
completed: false
}) { id }
}query list {
listTodos {
items {
id
name
completed
}
}
}

Now we can test out the API from our client side application.

First, we need to update our client side configuration to identify our AppSync API.

Create a new file called appsync-config.js in the root of the project:

Next, where we configured the Amplify client, let’s update it to also recognize our AppSync configuration:

import { AppRegistry } from 'react-native';
import App from './App';import Amplify from 'aws-amplify'
import config from './aws-exports'
import AppSyncConfig from './appsync-config' // NEW
Amplify.configure({ ...config, ...AppSyncConfig }
) // UPDATEDAppRegistry.registerComponent('ServerlessProject', () => App);

Now, we can easily create and execute operations against the API using the API category and graphqlOperation helper from AWS Amplify.

In App.js, let’s add a query:

Push Notifications

Push Notifications are available for both Android & iOS in AWS Amplify.

To enable the Push Notification service, you should go to the Pinpoint console by running awsmobile console and clicking on Resources then under Amazon Pinpoint click the link to your service.

The initial configuration for Push Notifications takes more time than any of the other services because we not only need to update some configuration for React Native, we also need to set up the actual services through Apple & Google.

I’ve written an article with a video walking through the entire process of setting up an iOS project here. The setup for Android can be found here.

Once your project is configured you can handle push notifications from with the app:

Conclusion

My Name is Nader Dabit . I am a Developer Advocate at AWS Mobile working with projects like AWS AppSync and AWS Amplify, and the founder of React Native Training.

If you enjoyed this article, please clap n number of times and share it! Thanks for your time.

When building a real-world mobile application there are a ton of essential basic requirements.
 You need to have a way to authenticate users, you want to track user engagement & usage, & you probably want to be able to send push notifications and maybe base these messages on events or user behavior. Then you have to manage your application data and are probably dealing with multiple REST endpoints. You’re also usually dealing with media such as images & videos and you hopefully want to be able t

--

--