Node.js API Tutorials

How to Create a Mobile App with NodeJS

What’s a Mobile Backend?

It does not take an expert to determine that the computing power of a server is most likely greater than the computing power of a mobile device.

If an application has a heavy computational load than it becomes more efficient for the mobile device to send parameters to a backend server to do the heavy lifting and then returning the result. A common pattern in React, when communicating between a front-end client and a back end server, is to use JSON.

This can become a simple process: a mobile app outsourcing it’s functionality to APIs with API requests for increased performance.

A mobile backend is simply the server, database, service, etc. that is not local to the mobile device that handles aspects of the processes of the mobile app.

View the Best Mobile App APIs List

MBaaS

Many companies, or developers, want to increase the functionality of their apps and they want it done quickly. In recent years, companies have been created to help increase the speed that mobile apps are developed and decrease the amount of work that goes into maintaining their architecture.

These companies are known as selling Mobile Backend as a Service (MBaaS). Furthermore, as described on Wikipedia, mobile backend as a service provides developers a, “…way to link their applications to backend cloud storage and APIs exposed by back end applications while also providing features such as user management, push notifications, and integration with social networking services.”

We will not be setting up any accounts with MBaaS providers for our application, but it could be considered in the design of your future mobile applications. Below is a list of popular MBaaS providers:

Express

With a myriad of HTTP utility methods and middleware at your disposal, creating a robust API is quick and easy.

Expressjs.com

Express is a Node.js framework for creating web application servers or APIs. Express is easy to set up, as you will see later and can be extended to include many features. Also, Express integrates all the benefits of Node.js (i.e asynchronous code).

Although Express can be a web application server, we are going to use it as an API to proxy our interactions with a database API.

Security

Whether developing front-end static websites, or a mobile application, security becomes an issue quickly. Reading from the Expo documentation,

Never put any secret keys inside of your app, there is no secure way to do this! Instead, you should store your secret key(s) on a server and expose an endpoint that makes API calls for your client and passes the data back.

Setting up an Express API on a server to handle the sensitive actions of our app allows us to secure secret keys. Later, we are going to demonstrate this process when we hide the value of our RapidAPI secret key.

Express Alternatives

To reiterate, some of the main advantages of Express are;

  • Node.js asynchronous code and performance
  • easy setup
  • extensible middleware
  • security

Considering the advantages, it’s safe to say that we are making a good choice when using Express. However, below is a list of other popular Node.js libraries that share some of the same functionality of Express:

All are reputable and have their advantages! You can read more about each by following the links. Ok, time to get started with the application!

How to Create a Mobile App with NodeJS

View the code on Github

The application is bootstrapped with Expo. Expo allows us to quickly set up a React Native project while providing a project structure so we can quickly get into coding out the components.

Furthermore, Expo is the nicest way to get started without being too picky about the type of operating system that you are using on your desktop or smartphone.

The application will use an Express server running locally to handle the database requests that are made using the FaiRESTdb API on RapidAPI as our database.

In addition to the individual use of React Native, Expo, and Express, this tutorial will show you how we can combine the three to create a secure mobile application that can store and retrieve data.

Prerequisites

1. Express and React Native Project Set-Up

Open up a new terminal and run the following commands

$ mkdir rapidapi-mobile-app-node
$ cd rapidapi-mobile-appj-node
$ npm install -g expo-cli
$ expo init expo-client

You are then prompted for the type of project to initialize by the Expo-CLI. Choose the managed workflow, tabs.

Change directories into the new project, cd expo-client.

In the apps root directory, run the command npm start and grab your smartphone.

Check to make sure that both your smartphone and computer are connected to the same wireless network.

If you are using Android, use the Expo client app to scan the QR-code that appears in the terminal (or the Qr-code in the web browser). If you are using iOS, you can use the camera’s built-in QR-code scanner. Select the camera app and point it at the QR-code.

After scanning, the Expo app opens and the Javascript bundle starts to build. This can take a couple of minutes. When it finishes, our app should appear on the smartphone with the template code. Your smartphone should now show the template code for our project!

It can take a few tries for the connection to stabilize

Observing the new project can be a little intimidating. However, it’s important to remember that many of the time-consuming aspects of setting up a mobile React Native project are handled with Expo.

To observe how we are going to develop the app, open up a text editor in the rapidapi-mobile-app-node folder, and make an edit to the file expo-client/screens/HomeScreen.js (make an edit to one of the <Text> components). This change will be reflected in the application running on your smartphone.

You do not need to have an Expo account to use the client app on your smartphone. After opening the app and scanning the QR-code, navigate to the Projects tab to open (or reopen) your project.

If you want to learn more about Expo, you can check out their documentation by following this link.

2. Code Express Server Routes

In your terminal, navigate to the root project directory: rapidapi-mobile-app-node.

In this directory execute the commands below.

$ mkdir express-server
$ cd express-server
$ npm init -y
$ npm install --save axios express dotenv
$ npm install --save-dev nodemon

The commands create a new NPM project and download some of the packages that we are going to use.

Nodemon is a development tool library that detects file changes in the project and restarts the development server. Add the below dev script to the package.json file in the express-server folder.

...
  "scripts": {
    "dev": "nodemon server.js -e js",
    ...
  },
...

Next, we can create the Express server. Create a new file in express-server named server.js and add the code,

const express = require('express');
const notesRouter = require('./routes/notes')

// Loads env variables
require('dotenv').config()

// Initalizes express server
const app = express();

// specifies what port to run the server on
const PORT = process.env.PORT || 3001;

// Adds json parsing middleware to incoming requests
app.use(express.json());

// makes the app aware of routes in another folder
app.use('/notes', notesRouter)

// console.log that your server is up and running
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));

Above is a basic Express server setup. After we add the /notes routes this server will be ready for use. Express is widely used because—with the code above—we have almost completely set up a working server.

Create Routes

Currently, server.js is importing a file that does not exist. Let’s create that file. In express-server, create the folder routes with the file notes.js.

Next, inside of the notes.js, add the code:

const router = require('express').Router()
const axios = require('axios')

// define the default route that fetches all of our notes
router.get('/', async function (req, res) {

    // data the conserves our API quota for development
    const placeholderData = [
        {
            "_id": "database1591127768852",
            "note": "Hello",
            "_createdOn": "2020-06-02T19:56:08.852Z",
            "_lastModifiedOn": "2020-06-02T19:56:08.852Z"
        },
        {
            "_id": "database1591134992139",
            "note": "New note",
            "_createdOn": "2020-06-02T21:56:32.139Z",
            "_lastModifiedOn": "2020-06-02T21:56:32.139Z"
        }
    ]

    try {
        // add api call

        res.json({ notes: placeholderData })
    } catch (e) {
        console.log(e)
        res.status(500).send('Error.')
    }
})

router.post('/add', async function (req, res) {
    // extract note text from request body
    const { note } = req.body

    const data = {
        note
    }

    console.log(note)

    try {
        // add api call

        res.json({
            message: 'Note added'
        })
    } catch (e) {
        console.log(e)
        res.status(500).send("Error.")
    }
})

router.post('/delete', async function (req, res) {
    // extract the note id to delete from request body
    const { noteId } = req.body

    console.log(noteId)

    try {
        // add api call

        res.send('Note deleted')
    } catch (e) {
        console.log(e)
        res.status(500).send('Error.')
    }
})

module.exports = router

This file defines three routes:

  • / returns all of our stored notes
  • /add adds a note
  • /delete deletes a note

Back in the server.js file, we imported the routes and gave them all a base URL of /notes. Therefore, the true URL for these routes is /notes/notes/add, and /notes/delete.

The file currently does not call the FaiRESTdb. We will add that later. For now, we are focusing on connecting the mobile front-end to the server.

Test Server Setup

In the terminal, checking to make sure that you are in the express-server folder, run npm run dev.

If Listening on port 3001 is logged to the terminal then the server has been set up correctly.

Keep the server running.

3. Connect React Native to Express Server

We can now start working on the user interface of our app.

Navigation

The first thing to change in the Expo app is the navigation labels. Our app will have two screens, and they will be titled ‘View Notes’ and ‘Add Note’.

Open expo-client/navigation/BottomTabNavigation.js.

Change the INITIAL_ROUTE_NAME variable to equal 'Notes'.

Next, change the string values for each of the <BottomTab.Screen> components to match the code below:

...
      <BottomTab.Screen
        name="Notes"                // change
        component={HomeScreen}
        options={{
          title: 'View Notes',     //change
          tabBarIcon: ({ focused }) => <TabBarIcon focused={focused} name="ios-list" />, // change 'name' for icon
        }}
      />
      <BottomTab.Screen
        name="Add"              // change
        component={LinksScreen}
        options={{
          title: 'Add Note',    // change
          tabBarIcon: ({ focused }) => <TabBarIcon focused={focused} name="ios-add" />, // change 'name for icon
        }}
      />
...

Then, make similar changes to the switch statement in the getHeaderTitle function.

...
  switch (routeName) {
    case 'Notes':    // changed
      return 'View Notes';   // changed
    case 'Add':     // changed
      return 'Add a note';   // changeed
  }
...

Finally, open expo-client/navigation/LinkingConfiguration.js and change the screens object to,

...
      screens: {
        Notes: 'notes',
        Add: 'add',
      },
...

Our navigation is now representative of our apps subject matter.

Homescreen.js

The Homescreen.js has a lot of code that we don’t need. Replace the code with the following simple components and accessory code.

import * as React from 'react';
import { StyleSheet, Text, TouchableOpacity, View, Button, FlatList, TouchableHighlight, Modal, Alert } from 'react-native';
import { Ionicons } from '@expo/vector-icons';


export default function HomeScreen() {
  let [notes, setNotes] = React.useState('')
  let [activeNote, setActiveNote] = React.useState('')

  const getNotes = () => {
    console.log('notes')
  }


  const createTwoButtonAlert = (id) => {
    setActiveNote(id)

    Alert.alert(
      "Note Options",
      "What action would you like to perform?",
      [
        {
          text: "Cancel",
          onPress: () => console.log("Cancel Pressed"),
          style: "cancel"
        },
        {
          text: "Delete",
          onPress: () => deleteNote(),
          style: "destructive"
        }
      ],
      { cancelable: false }
    );
  }

  return (
    <View style={styles.container}>


      <View style={styles.description}>
        <Text style={{ textAlign: "center" }}>Keep track of all your notes in an easily accessible application!</Text>
        <TouchableOpacity
          onPress={() => getNotes()}>
          <Ionicons
            name={'md-refresh'}
            size={30}
            style={{ margin: 3 }}
            color={'green'}
          />
        </TouchableOpacity>
      </View>


      <FlatList
        data={notes}
        renderItem={({ item }) =>
          <TouchableHighlight
            activeOpacity={0.6}
            underlayColor="#DDDDDD"
            key={item._id}
            onPress={() => createTwoButtonAlert(item._id)}>
            <View key={item._id} style={styles.task}>
              <Text>{item.note}</Text>
            </View>
          </TouchableHighlight>
        }
        keyExtractor={(item, index) => index.toString()}
      />
    </View>
  );
}

HomeScreen.navigationOptions = {
  header: null,
};

const styles = StyleSheet.create({
  task: {
    marginVertical: 4,
    marginHorizontal: 8,
    backgroundColor: 'yellow',
    paddingHorizontal: 6,
    paddingVertical: 15
  },
  container: {
    flex: 1,
    display: "flex"
  },
  description: {
    display: "flex",
    alignItems: "center",
    marginVertical: 20,
  }
});

At the top of the file, we are making the necessary imports from react-native. Also, we are importing icons from Expo.

Next, we are defining our Homescreen React component function. Inside the function, we immediately use React hooks to create two state variables ( notes, activeNote).

After the state variables we declare two functions:

  1. getNotes will be used to retrieve the notes from the server
  2. createTwoButtonAlert is used to generate an alert popup when a note is selected to provide actions to be executed on the note

Finally, we create React Native components, which are currently not utilized (because we have no notes). The app on your phone should now look like this.

Add the getNotes Function

The getNotes function is a simple fetch API call to the Node server that is running on our computer. This function is also going to be run when the app loads, and we are going to use the React useEffect hook to accomplish that.

We could have put the fetch function inside the useEffect hook, but we wanted to expose the function to be used outside of the hook (i.e to refresh the notes).

Complete the getNotes function and add the useEffect hook to our component with the code below.

...
  const getNotes = React.useCallback(() => {
    fetch('http://localIPaddress:3001/notes')
      .then((response) => response.json())
      .then((json) => {
        setNotes(json.notes)
      })
      .catch(error => {
        console.log(error)
      })
  }, [])

  React.useEffect(() => {
    getNotes()
  }, [getNotes])
...

This will almost work (if your Node server is still running). We can’t use localhost in this situation because the Expo app is running on a different device than our computer. However, they are using the same WiFi network. This means that we can find the local IP address of our computer (that is running the Express server) and enter that IP address into the URL of the fetch function.

Find Your Local IP Address

On Mac, open up your Network Preferences.

My local IP address 192.168.0.110. Therefore, my Express server is running at http://192.168.0.110:3001. We added :3001  to the end of the address because that’s the port that we chose to expose the Express app on.

This IP address is also referred to as your private IP address.

On Windows, open up the Command Prompt and enter ipconfig.

The terminal will display network information. Your private IP address is the IP address with the label IPv4 address:

Once you have this information, replace the localIPaddress part of the fetch function with your private IP address.

The application is now able to fetch the placeholderData from the default /notes route on the server. You should see the placeholder notes after you reload your app.

We now have communication between our mobile app and backend server!

Add the deleteNote Function

When you select a note there is an alert pop-up that asks if you want to delete the note. Unfortunately, we have not added this function to the app.

Underneath the React.useEffect hook add:

...
  const deleteNote = () => {
    fetch('http://localIPaddress:3001/notes/delete', {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        noteId: activeNote
      })
    })
      .then(() => {
        // make a copy of current notes
        const newNotes = [...notes]

        // filter out note that is being deleted
        const filtered = newNotes.filter(({ _id }) => {
          return _id !== activeNote
        })

        // set filtered array as new state
        setNotes(filtered)
      })
      .catch(error => {
        console.log(error)
      })
  }
...

The function sends the activeNote ID to the server for deletion. Also, it filters the current notes array and saves a new array without the note that was deleted.

Again, you need to add your IP address to the fetch URL.

LinksScreen.js

This file is used for adding a note to the database. Therefore, replace the current code with the code below.

import * as React from 'react';
import { StyleSheet, TouchableHighlight, Modal, Text, View, Button, TextInput } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';
import { Ionicons } from '@expo/vector-icons';

export default function LinksScreen() {
  const [text, onChangeText] = React.useState('');
  const [modalVisible, setModalVisible] = React.useState(false);

  const addNote = () => {
    fetch('http://localIPaddress:3001/notes/add', {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        note: text
      })
    })
    .then(() => {
      onChangeText('');
      setModalVisible(true)
    })
  }

  return (
    <ScrollView style={{flex: 1}}>
      <Modal
        animationType="slide"
        transparent={true}
        visible={modalVisible}
        onRequestClose={() => {
          Alert.alert("Modal has been closed.");
        }}
      >
        <View style={styles.centeredView}>
          <View style={styles.modalView}>
            <Text style={styles.modalText}>Success!</Text>
            <Ionicons
              name={'md-checkmark-circle'}
              size={50}
              style={{ marginBottom: -3 }}
              color={'green'}
            />
            <TouchableHighlight
              style={{ ...styles.openButton, borderWidth: 1, borderStyle: "solid", borderColor: "#2196F3" }}
              onPress={() => {
                setModalVisible(!modalVisible);
              }}
            >
              <Text style={styles.textStyle}>Add Another Note</Text>
            </TouchableHighlight>
          </View>
        </View>
      </Modal>


      <View>
        <TextInput
          style={styles.input}
          onChangeText={text => onChangeText(text)}
          value={text}
          multiline
          numberOfLines={10}
          placeholder={'Learn typescript..'}
        />
        <View style={styles.button}>
          <Button
              onPress={() => {
                addNote();
              }}
              title="Add"
              color="white"
            />
        </View>
      </View>
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  input: {
    height: 100,
    borderColor: 'gray',
    borderWidth: 1,
    marginHorizontal: 5,
    marginVertical: 20,
    padding: 10
  },
  button: {
    marginHorizontal: 5,
    backgroundColor: 'blue',
  },
  centeredView: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    marginTop: 22
  },
  modalView: {
    margin: 20,
    backgroundColor: "white",
    borderRadius: 20,
    padding: 35,
    alignItems: "center",
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5
  },
  openButton: {
    borderColor: "#F194FF",
    backgroundColor: 'white',
    borderRadius: 10,
    padding: 10,
    elevation: 2
  },
  textStyle: {
    color: "#2196F3",
    fontWeight: "bold",
    textAlign: "center"
  },
  modalText: {
    marginBottom: 10,
    textAlign: "center",
    fontSize: 40
  }
});

It looks likes a lot of code, but the bottom section is mostly styling. The screen is an input component with a submit button and a modal informing the user that the note was added successfully. The LinksScreen, or Add Note screen now looks like the image below.

Test the Routes

We can now use the app and make sure that our data is being passed between the server and the application properly.

First, we can assume that the /notes route is working because we can render the placeholder data.

Next, try to delete one of the notes by selecting it and choosing Delete. The terminal running our Express server should log the note’s ID and the note should temporarily disappear from the home screen of the application.

Finally, try adding a note. The note content should be logged to the server terminal and the success modal should appear!

Perfect! We are now ready to hook up the backend to an API database service.

4. Add FaiRESTdb API Calls to Server

Sign Up For a Free Account on RapidAPI

To use the FaiRESTdb API in the next section, you will need an account. Visit RapidAPI to get signed up!

Subscribe to the FaiRESTdb API

Next, subscribe to the FaiRESTdb API to have the ability to save notes. Follow this link to the Pricing page.

Notice I have already subscribed to the Basic plan, therefore I have a link to Manage and View Usage that takes me to the developer dashboard.

You can track your API usage on the dashboard in case you have concerns about approaching your quota for any of the APIs that you subscribe to.

The API allows us 500 API requests a month then $0.01 each request above that amount.

We going to use the RapidAPI dashboard for the API to set up a database to use with our app.

Create a database for mobile application

Navigate to the endpoints page of the API.

The different types of endpoints that are available and can be found on the left side of the interactive dashboard.

Depending on which endpoint is selected, a definition and parameter information will be available in the center of the dashboard.

Finally, the right side of the dashboard builds code snippets based on the endpoint and the parameters that we enter. In this way, the dashboard works from left-to-right.

In addition to ready-to-use code snippets, the right side of the dashboard displays sample response objects that are important to planning our application. Most APIs allow us to test endpoints and receive real response data right in the API dashboard.

We can create a database for our sample application in the dashboard after subscribing because the tests are real requests.

Select the Create Database endpoint.

Scroll down and change the "name" value in the Request Body to notes.

Next, hit Test Endpoint. The Results section of the dashboard displays a successful response object.

Create a Model for the Database

Just like we did for the database, we need to select the endpoint, fill in the parameters, and send the request.

Select the Create Model endpoint and add the appropriate parameters.

Remember to change the database argument to notes.

Hit Test Endpoint again and observe the successful response.

We are now ready to add notes to our app.

Add Axios API Calls

You may remember that the express-server/routes/notes.js file had comments, in each route, that read // add api call.

Now, we are going to replace those comments with the actual code for the API.

Add the below code blocks to the respective route declaration.

For the default / route, delete the placeholderData variables and replace the comment with;

...
        const { data } = await axios({
            method: 'GET',
            url: "https://fairestdb.p.rapidapi.com/notes/note",
            headers: {
                "x-rapidapi-host": "fairestdb.p.rapidapi.com",
                "x-rapidapi-key": process.env.RAPIDAPI_KEY,
                "useQueryString": true
            }
        })
...

Then, change the response to send back the data variable and not the placeholderData variable.

In the /add route, replace the comment with;

...
        await axios({
            method: 'POST',
            url: "https://fairestdb.p.rapidapi.com/notes/note",
            data,
            headers: {
                "content-type": "application/json",
                "accept": "application/json",
                "x-rapidapi-host": "fairestdb.p.rapidapi.com",
                "x-rapidapi-key": process.env.RAPIDAPI_KEY,
                "useQueryString": true
            }
        })
...

Lastly, replace the comment in the /delete route with the code below;

...
        await axios({
            method: "DELETE",
            url: "https://fairestdb.p.rapidapi.com/notes/note/_id/"+noteId,
            headers: {
                "x-rapidapi-host": "fairestdb.p.rapidapi.com",
                "x-rapidapi-key": process.env.RAPIDAPI_KEY,
                "useQueryString": true
            }
        })
...

The routes are almost ready but we need to add our API key to the environment.

Add API key

Create a file in the same directory as the server.js file named .env. Here, we can add secret environment variables that are injected into the app’s environment. This allows us to keep our API keys safe in development and production.

Inside of .env add the line,

RAPIDAPI_KEY=rapidapikey

replacing rapidapikey with your API key.

5. Test the Application

Restart the Express server in the terminal so you can use the environment variable that was added.

Then, reopen the app and add a couple of notes. Finally, head back over to the home screen and click the green refresh button.

Your notes should now appear! They will also appear if you were to close and reopen the app because they are stored in a database using the API.

Conclusion

This application tutorial teaches you how to connect an Express backend server to a mobile client for developing an application. If you are coming from a React or NodeJS background it may be easier for you to write code with NodeJS on a server compared to React Native on a client. This is one of the benefits of setting up an Express backend.

The application is not production-ready. The server would need to be deployed to a production environment and the client API calls would need some adjusting. Furthermore, the app can only have one user!

Despite the app’s shortcomings, many important aspects of mobile app development are within our reach with this setup. If you have questions or comments please leave a reply below!

View the Best Mobile App APIs List

5/5 - (3 votes)

View Comments

Share
Published by

Recent Posts

Power Up Your Enterprise Hub: New March Release Boosts Admin Capabilities and Streamlines Integrations

We're thrilled to announce the latest update to the Rapid Enterprise API Hub (version 2024.3)!…

2 weeks ago

Unveiling User Intent: How Search Term Insights Can Empower Your Enterprise API Hub

Are you curious about what your API consumers are searching for? Is your Hub effectively…

2 weeks ago

Rapid Enterprise API Hub Levels Up Custom Branding, Monetization, and Management in February Release

The RapidAPI team is excited to announce the February 2024 update (version 2024.2) for the…

4 weeks ago

Supercharge Your Enterprise Hub with January’s Release: Search Insights, Login Flexibility, and More!

This January's release brings exciting features and improvements designed to empower you and your developers.…

3 months ago

Enhanced Functionality and Improved User Experience with the Rapid API Enterprise Hub November 2023 Release

Rapid API is committed to providing its users with the best possible experience, and the…

5 months ago

The Power of Supporting Multiple API Gateways in an API Marketplace Platform

In today's fast-paced digital world, APIs (Application Programming Interfaces) have become the backbone of modern…

6 months ago