How to Build a Simple Chat App with React Native and Firebase

By |November 30th, 2017|Categories: Front-End, JavaScript, React, Redux, Uncategorized|Tags: , , , |

Nick is a mobile developer with wide experience in building iOS and Android applications at RubyGarage. He enjoys researching tech topics and sharing his knowledge with other developers.

In mobile development, cross-platform applications are appreciated for their short development cycle, low cost, and quick time to market in comparison with native apps.

One popular framework that enables developers to build hybrid mobile apps is React Native. React Native was created by Facebook developers during a hackathon back in 2013. Since then, the framework has become a core technology for numerous mobile applications including Instagram, Skype, Tesla, Airbnb, and Walmart.

React Native has gained popularity mainly because it allows for fantastic reuse of code on iOS and Android platforms. In fact, Facebook claims they reused around 85% of their code while developing their iOS and Android mobile apps.

In short, React Native is an effective framework for building mobile apps and in particular their frontend parts.

When you build a full-fledged application, however, you have to rely on the backend as well. For this purpose, you can use Firebase. Firebase is backend-as-a-service software, so you don’t have to deal with routine tasks like database setup, hosting, and storage. As a result, Firebase saves time and allows you to focus on development.

In this tutorial, I’ll show you how to build a simple chat application with React Native and Firebase. Interested? Let’s dive in!

About the Application

The application we’re going to build will be available on both iOS and Android. The app consists of three screens: sign-up, login, and chat.

We’ll let users sign up and log in with an email and password. For user sign-up and login, we’ll use Firebase Authentication.

The chat will be available for signed-in users only. The messaging functionality will be implemented with the help of the Firebase Realtime Database.

Since we’re creating a simple chat app, we won’t let users create and join groups. All users will be in the same group.

mockup

Libraries for Creating the Chat App

Here’s the list of libraries that we’ll use to build the chat app:

  • firebase – the client-side libraries for applications that use Firebase services
  • react – a JavaScript library for building user interfaces
  • react-native – a framework for building native apps with React
  • react-native-i18n – a library that provides internationalization with React Native
  • react-navigation ‒ a library that implements navigation logic
  • react-redux – official React bindings for Redux
  • redux ‒ a state management library for JavaScript applications
  • redux-thunk ‒ middleware that returns functions of actions
  • eslint ‒ a linting utility for JavaScript applications
  • relative-date – JavaScript module for outputting relative dates

1. Setting Up Firebase

First, let’s start with setting up Firebase as our backend. This involves creating an account, setting up a login method, copying the config, and adding the config to our application.

Create an Account

  1. Go to the Firebase website and click Go to Console in the header menu.
  2. Click Add project. Give your project a name and select your country or region.

Set Up a Login Method

To enable users to sign in with various methods including email and password as well as popular social media accounts like Twitter and Facebook, we’ll need to set up a login method.

  1. In the left menu, select Authorization and then click Set up sign-in method.
  2. Enable the sign-in methods you want your users to authorize with. In this tutorial, we’ll use email and password authorization.

Add Firebase to Your Application

Here’s how to integrate Firebase into your app:

  1. Click the gear icon in the top-left menu and select Project settings in the pop-up menu.
  2. Click Add Firebase to your web app and copy the snippet that’s automatically generated.

2. Building a Chat App with React Native

Set Up the Initial Project

After Firebase (the backend part of our application) is set up, it’s time to work on the frontend.

First, initialize the project with the following command:

Next, install the libraries that are required for the project:

To make sure that the application works properly, launch the iOS application with the following command:

For the Android application, run this command:

3. Create the Firebase Component

Our application’s essential features like login, registration, and message sending require a service that works with Firebase.

Add the config that you previously copied to a new file named firebase.js.

app/configs/firebase.js

After that, let’s create the service itself, using the config:

app/services/firebase.js

4. Set Up the Redux

As I mentioned, we’ll use the Redux library to manage the application state. For that purpose, let’s create two reducers: session will implement the login and registration functionality, while chat will implement chat messaging.

The list of all possible login and registration actions that may impact the application state are put into a separate file, actionTypes.js:

  • SESSION_RESTORING ‒ restores user sessions. Firebase restores user sessions asynchronously, so the system will display a preloader until the action is completed.
  • SESSION_LOADING ‒ displays a preloader until the login or registration request has been processed by Firebase.
  • SESSION_SUCCESS ‒ transfers a user to the chat screen after login has successfully completed
  • SESSION_ERROR ‒ displays login or registration errors
  • SESSION_LOGOUT ‒ displays the login screen

app/store/session/actionTypes.js

For the chat, the available actions are as follows:

  • CHAT_MESSAGE_LOADING ‒ blocks the buttons when sending a message to Firebase
  • CHAT_MESSAGE_SUCCESS ‒ clears the field after a message is successfully sent
  • CHAT_MESSAGE_ERROR ‒ displays errors when sending a message
  • CHAT_MESSAGE_UPDATE ‒ edits the current message in a chat
  • CHAT_LOAD_MESSAGES_SUCCESS ‒ updates the messages list after the application uploads new messages from Firebase
  • CHAT_LOAD_MESSAGES_ERROR ‒ displays an error if the message list fails to upload

app/store/chat/actionTypes.js

To manage a user session, we’ll need a reducer (let’s call it a session). This reducer will change the application’s state when restoring a user session or interacting with the login and registration screens. For example, after a user sends a login request, the system may display either Success or Error.

app/store/session/reducer.js

To manage the chat, let’s create a reducer and call it chat. This reducer will manage the application’s state when messages are created, uploaded, or edited.

app/store/chat/reducer.js

Each of reducers manages an independent state part. To combine these parts into a single store, let’s use the combineReducers helper function.

app/store/reducer.js

When the state changes, the application components receive that state and change the view–for example, updating the UI.

I18n

To localize the application, we’ll use the react-native-i18n library. This library enables content translation and localization for multiple languages.

app/i18n/index.js

5. Application Component

We’ll use the application component to restore user sessions and display the login, registration, or chat screen depending on whether a user is logged in or logged out.

Let’s break this component into two files. The Container.js file will listen to state changes and prepare the data for the UI component. Component.js will be in charge of implementing the UI.

We’ll follow the same rule and break each component in two files. The Container.js file will work on business logic; the Component.js will work on the UI part.

app/components/ChatApp/Component.js

app/components/ChatApp/Container.js

6. Sign Up and Sign In

In order to manage user sessions, we’ll need methods to send requests to Firebase and dispatch actions depending on the result returned.

To restore a user session, let’s create a restoreSession method that will keep track of the user authentication state and send actions in order to transfer a user to the login screen or the chat screen.

app/store/session/actions.js

Create the loginUser method to authenticate a user in Firebase:

app/store/session/actions.js

Create a signupUser method to register a user in Firebase:

app/store/session/actions.js

The Sign Up and Sign In screen interfaces consist of a loading indicator that shows the progress of the Firebase query. Two tabs contain the login and registration forms.

Let’s create a component that will be the wrapper for the login and registration tabs and will display the loading indicator and any errors. This component will keep track of state changes and, for loading or errors, display an indicator or an error alert.

app/components/AuthScreen/Component.js

app/components/AuthScreen/Container.js

To create this component with tabs, we’ll use the react-navigation library and a TabNavigator component. In TabNavigator, we’ll specify which component will be displayed in each tab and will set the tab style.

app/components/AuthScreen/AuthTabs/index.js

The only element that’s different between the login and registration forms is the name of the button and the method that’s called after a user pushes that button.

That’s why we’ll create a basic component for the form and transfer the name of the button and the called method to that component.

app/components/AuthScreen/AuthTabs/BasicForm/Component.js

Next, let’s create a component for the login form. To do so, set up the text and the icon that will be displayed in the parent component that contains the tabs. We’ll pass the function that sends user data for the Firebase login to the basic component.

app/components/AuthScreen/AuthTabs/LoginForm/Component.js

app/components/AuthScreen/AuthTabs/LoginForm/Container.js

Repeat the same process for the registration form.

app/components/AuthScreen/AuthTabs/SignUpForm/Component.js

app/components/AuthScreen/AuthTabs/SignUpForm/Container.js

As a result, you’ll get the view screen:

view screen

7. Chat

To create new messages and load the current list of messages, we’ll need methods that work with Firebase. Create a loadMessages method to load the current list of messages.

app/store/chat/actions.js

Use the updateMessage method to hold the message currently being typed by a user.

app/store/chat/actions.js

To enable message sending, use the sendMessage method. Also, we need to create the message structure that will be stored in the Firebase Realtime Database.

app/store/chat/actions.js

For the chat interface, let’s use the StackNavigator component from the react-navigation library. This component displays the top bar with the title of the application.

app/components/DashboardNavigator/index.js

The ChatScreen component deals with adjusting the title text and displaying the list of messages along with the new message form. Note that due to differences in system features, you’ll need to handle hiding keyboards differently for iOS and Android. For that purpose, let’s use ReactNative’s out-of-the-box features and add suffixes .ios and .android to the filenames so the system will automatically load the necessary file.

app/components/DashboardNavigator/ChatScreen/Component.android.js

app/components/DashboardNavigator/ChatScreen/Component.ios.js

app/components/DashboardNavigator/ChatScreen/Container.js

The MessageForm component is responsible for sending a new message to Firebase. While a message is being sent, we’ll block the buttons and the text field to prevent a user from accidentally editing the text or resending the message.

app/components/DashboardNavigator/ChatScreen/MessageForm/Component.js

app/components/DashboardNavigator/ChatScreen/MessageForm/Container.js

Add a component that keeps track of changes in the chat and displays the messages list. This component will also display the error text if a message fails to send.

app/components/DashboardNavigator/ChatScreen/MessagesList/Component.js

app/components/DashboardNavigator/ChatScreen/MessagesList/Container.js

The MessageRow component displays each message in the list. Let’s separate the user’s messages from correspondents’ messages by placing the user’s text on the right and correspondents’ text on the left.

app/components/DashboardNavigator/ChatScreen/MessagesList/MessageRow/Component.js

app/components/DashboardNavigator/ChatScreen/MessagesList/MessageRow/Container.js

chat alignment

8. Logout

To enable a user to log out, the application sends a query to Firebase. Let’s create the function that will send this query. After the query is processed, the application will change its state and display the login screen.

app/store/session/actions.js

Finally, let’s create a separate component to display a logout icon and call the logout function.

app/components/DashboardNavigator/ChatScreen/LogoutButton/Component.js

app/components/DashboardNavigator/ChatScreen/LogoutButton/Container.js

9. Check out the complete application

As you can see, building an application with React Native is easy. All you need is a little patience.

You can check out the complete application on GitHub. If you have any questions or suggestions, feel free to get in touch with me!

Nick
Nick is a mobile developer with wide experience in building iOS and Android applications at RubyGarage. He enjoys researching tech topics and sharing his knowledge with other developers.