Firebase

Firebase is a Mobile Backend as a Service (MBaaS), which means that it provides mobile developers with all the backend necessities, such as user management, no SQL database, and a push notification server. It integrates easily with React Native through an official node package, which brings the database connection for free. Unfortunately, Firebase doesn't offer a JavaScript SDK for their push notifications service, but there are several React Native libraries filling that gap by bridging Firebase's iOS and Java SDKs with a JavaScript interface. We will be using react-native-fcm as it is the most mature in its field.

Before building an app on top of a Firebase MBaaS, you need to create a project for it. This is a free process that is explained in Firebase's website https://firebase.google.com/. Although this process is not directly related to React Native, it's a good starting point to understand how to set up and use a MBaaS for our apps. Most of the configuring can be finished in a matter of minutes just by following the tutorials available on Firebase's documentation site. The benefits of setting up this MBaaS make those minutes worth the time and initial hassle.

To set up Firebase and connect our app to the correct project, we need to use the configuration for the web snippet we can find in the Settings screen inside our Firebase project's dashboard. We added this initialization snippet on src/firebase.js:

import firebase from 'firebase';

var firebaseConfig = {
  apiKey: “<Your Firebase API key>",
  authDomain: “<Your Firebase Auth domain>",
  databaseURL: “<Your Firebase database URL>",
  projectId: “<Your Firebase projectId>",
  storageBucket: “<Your Firebase storageBucket>",
  messagingSenderId: “<Your messaging SenderId>"
};

export const firebaseApp = firebase.initializeApp(firebaseConfig);

Once the project is set up, we can start taking a look at how our database is going to be structured.

Real-Time Database

Firebase allows mobile developers to store and sync data between users and devices in real time using a cloud-hosted, NoSQL database. Updated data syncs across connected devices in milliseconds and data remains available if your app goes offline, providing a great user experience regardless of network connectivity.

Three data models come into the picture when thinking about the basic data a one-to-one communication app should handle:

  • users: This will store avatars, names, and push notification tokens. There is no need to store authentication data here as it is handled through a different Firebase API (authentication API).
  • messages: We will save each message on each chat room separately for easy retrieval using the chat room ID as a key.
  • chats: All the information about the opened chats will be stored here.

To understand how we will request and use the data in our app, let's see a gist of the example data we can actually use for testing:

{
  “chats" : {
    “--userId1--" : {
      “--userId2----userId1--" : {
        “contactId" : “--userId2--",
        “image" : “https://images.com/person2.jpg",
        “name" : “Jason"
      }
    },
    “--userId2--" : {
      “--userId2----userId1--" : {
        “contactId" : “--userId1--",
        “image" : “https://images.com/person1.jpg",
        “name" : “John"
      }
    }
  },
  “messages" : {
    “--userId2----userId1--" : {
      “-KpEwU8sr01vHSy3qvRY" : {
        “_id" : “2367ad00-301d-46b5-a7b5-97cb88781489",
        “createdAt" : 1500284842672,
        “text" : “Hey man!",
        “user" : {
          “_id" : “--userId2--",
          “name" : “Jason"
        }
      }
    }
  },
  “users" : {
    “--userId1--" : {
      “name" : “John",
      “notificationsToken" : “"
    },
    “--userId2--" : {
      “name" : “Jason",
      “notificationsToken" : “--notificationsId1--"
    }
  }
}

We organized our data in a way it will be easy for the messaging app to retrieve and synchronize. Instead of normalizing the data structure, we introduced some data duplication to increase speed during data retrieval and simplify the frontend code to the maximum.

The users collection holds the users' data using the user ID as a key (--user1--, and --user2--). These user IDs are retrieved automatically by Firebase during registration/login. Each user has a notification token, which is an identifier for the device the user is logged in with the push notifications service. When the user logs out, the notifications token is removed, so messages sent to this user will be stored, but not notified to any device.

The chats collection stores each user's chat list by user ID. Each chat has its own ID (a concatenation of both user IDs) and will be duplicated as every user on that chat should have a copy of the chat data. In each copy, there is enough information for the other user to build up their chat screen.

The messages collection is stored in a separate collection, which can be referenced by that ID. Each chat ID points to a list of messages (only one in this example) where all the data needed by the chat screen is stored. There is also some duplication in this collection as some user data is stored together with each message to reduce the number of requests needed when building a chat screen.

A full tutorial on how to read and write data in Firebase's real-time database can be found on their website (https://firebase.google.com/docs/database/), but we will take a quick look at the methods we will be using in this lesson.

Reading Data from Firebase's Database

There are two ways for retrieving data from Firebase's database. The first one sets a listener that will be called every time the data changes, so we only need to set it up once for the entire lifetime of our app:

firebaseApp.database().ref('/users/' + userId).on('value', (snapshot) => {
  const userObj = snapshot.val();
  this.name = userObj.name;
  this.avatar = userObj.avatar;
});

As we can see, in order to retrieve a snapshot of data, we need to call the database() method in our firebaseApp object (the one we created in our src/firebase.js file). Then, we will have a database object where we can call the ref('<uri>') on it passing the URI, where the data is stored. That will return a reference to the piece of data pointed by that URI. We can go for the on('value', callback) method, which will attach a callback passing the snapshot of data. Firebase always returns objects as snapshots, so we need to transform them into plain data ourselves. In this example, we want to retrieve an object with two keys (name and avatar), so we only need to call the val() method on the snapshot to retrieve a plain object containing the data.

If we don't need the retrieved data to be automatically synched every time it is updated, we could have used the once() method instead of on():

import firebase from 'firebase';
import { firebaseApp } from '../firebase';

firebaseApp.database().ref('/users/' + userId).once('value')
.then((snapshot) => {
  const userObj = snapshot.val();
  this.name = userObj.name;
  this.avatar = userObj.avatar;
});

The callback receiving snapshot will only be called once.

Updating Data in Firebase's Database

Writing data in a Firebase database can also be done in two different ways:

firebaseApp.database().ref('/users/' + userId).update({
  name: userName
});

The update() method changes the object referenced by the supplied URI according to the keys and values passed as a parameter. The rest of the object is left intact.

On the other hand, set() will replace the object in the database with the one we provide as a parameter:

firebaseApp.database().ref('/users/' + userId).set({
  name: userName,
  avatar: avatarURL
});

Finally, if we want to add a new snapshot of data but we want Firebase to generate an ID for it, we can use the push method:

firebaseApp.database().ref('/messages/' + chatId).push().set(message);

Authentication

We will use Firebase authentication services, so we don't need to worry about storing login credentials, handling forgotten passwords, or verifying emails on our side. These and other related tasks come for free with Firebase authentication services.

In order to activate login and registration through email and password, we need to enable this method as a session sign-in method in our Firebase dashboard. More information about how to do this can be found on Firebase's website at https://firebase.google.com/docs/auth/web/password-auth.

In our app, we only need to use the provided Firebase SDK for login:

firebase.auth().signInWithEmailAndPassword(username, password)
  .then(() => {
        //user is logged in
  })
  .catch(() => {
        //error logging in
  })
})

For registration, we can use the following code:

firebase.auth().createUserWithEmailAndPassword(email, password)
.then((user) => {
   //user is registered
})
.catch((error) => {
   //error registering
})

All the token handling will be taken care of by Firebase, and we only need to add a listener to make sure our app is updated when the authentication status changes:

firebase.auth().onAuthStateChanged((user) => {
  //user has logged in or out
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.103.28