Start With React Native & Firebase: Authentication and Realtime Database services

Sohad Dader
8 min readDec 11, 2018

In this tutorial, we will build a React Native app that uses Firebase Authentication with email and Realtime Database services, you can find out more about Firebase by visiting their own site.

Please note that this tutorial assumes you have some JavaScript or React Native experience. I have made the code as simple as possible, if you have any questions, please do not hesitate to leave a comment.

Let’s begin 🤓 💪🏻

Step 1. Create a Firebase account

The first step will be to head over to Firebase and create a free account.

Greate Project

To create a new firebase project, go to your Firebase console, click “Add Project”, type in your project’s name and select your region.

After that Enable Email Login:

  • On the Sign in method tab, enable the Email sign-in method.

Now we need to tell the firebase library: “Hey”, so, to complete the installation we will do these steps for iOS. And these for Android.

Step 2. Getting Started:

If this is your first time creating a React Native app, make sure you have Node, npm. And then create your App.

Then build your structure for React Native project. I prefer to build it like this.

Step 3. Install Dependencies:

Now will be adding firebase to our project. Open up your terminal to run this command.

npm install --save react-native-firebase

Step 4. Creating our Screens:

We will create four screens for our app, these four screens are Loading, SignUp, Login, and Home.

A Loading screen that displays until we determine the auth state of a user, a SignUp screen where the user can create an account, a Login screen where an existing user can login, and a Home screen of our application that we only show to an authenticated user.

We’re going to be using react-navigation for our app’s navigation, so let’s set up our navigator and create our screens.

npm install react-navigation --save

Let’s create our screens:

Loading.js

import React from 'react'
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native'

export default class Loading extends React.Component {
render() {
return (
<View style={styles.container}><Text style={{color:'#e93766', fontSize: 40}}>Loading</Text><ActivityIndicator color='#e93766' size="large" /></View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
})

SignUp.js

import React from 'react'
import { StyleSheet, Text, TextInput, View, Button, TouchableOpacity } from 'react-native'
import styles from './style'

export default class signUp extends React.Component {
state = { email: '', password: '', errorMessage: null }
handleSignUp = () => {
// TODO: For Firebase athu
console.log('handleSignUp')
}

render() {
return (
<View style={styles.container}>
<Text style={{color:'#e93766', fontSize: 40}}>Sign Up</Text>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>}
<TextInput
placeholder="Email"
autoCapitalize="none"
style={styles.textInput}
onChangeText ​={email => this.setState({ email })}
value={this.state.email}
/>
<TextInput
secureTextEntry
placeholder="Password"
autoCapitalize="none"
style={styles.textInput}
onChangeText ​={password => this.setState({ password })}
value={this.state.password}
/>
<Button title="Sign Up" color="#e93766" onPress ​={this.handleSignUp}/>
<View>
<Text> Already have an account? <Text onPress ​={() => this.props.navigation.navigate('Login')} style={{color:'#e93766', fontSize: 18}}> Login </Text></Text>
</View>
</View>
)
}
}

style.js

import {StyleSheet} from 'react-native';
export default {
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
textInput: {
height: 40,
fontSize:20,
width: '90%',
borderColor: '#9b9b9b',
borderBottomWidth: 1,
marginTop: 8,
marginVertical: 15
}
}
Sign Up Screen

Login.js

import React from 'react'
import { StyleSheet, Text, TextInput, View, Button } from 'react-native'
import styles from './style'
export default class Login extends React.Component {
state = { email: '', password: '', errorMessage: null }
handleLogin = () => {
// TODO: Firebase stuff...
console.log('handleLogin')
}
render() {
return (
<View style={styles.container}>
<Text style={{color:'#e93766', fontSize: 40}}>Login</Text>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>}
<TextInput
style={styles.textInput}
autoCapitalize="none"
placeholder="Email"
onChangeText={email => this.setState({ email })}
value={this.state.email}
/>
<TextInput
secureTextEntry
style={styles.textInput}
autoCapitalize="none"
placeholder="Password"
onChangeText={password => this.setState({ password })}
value={this.state.password}
/>
<Button title="Login" color="#e93766" onPress={this.handleLogin} />
<View>
<Text> Don't have an account? <Text onPress={() => this.props.navigation.navigate('SignUp')} style={{color:'#e93766', fontSize: 18}}> Sign Up </Text></Text>
</View>
</View>
)
}
}

Style.js

import {StyleSheet} from 'react-native';
export default {
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
textInput: {
height: 40,
fontSize:20,
width: '90%',
borderColor: '#9b9b9b',
borderBottomWidth: 1,
marginTop: 8,
marginVertical: 15
}
}

Home.js

import React from 'react'
import { StyleSheet, Platform, Image, Text, View } from 'react-native'

export default class Home extends React.Component {
state = { currentUser: null }
render() {
const { currentUser } = this.state
return (
<View style={styles.container}><Text>
Hi {currentUser && currentUser.email}!
</Text></View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})

Now that we have all our screens created, let’s wire up our navigation inside our App.js file.

App.js

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import { SwitchNavigator } from 'react-navigation'
import Loading from '@screens/Loading'
import SignUp from '@screens/SignUp'
import Login from '@screens/Login'
import Home from '@screens/Home'
import config from './src/common/constants.js';


const App = SwitchNavigator(
{
Loading,
SignUp,
Login,
Home
},
{
initialRouteName: 'Loading'
}
)


export default App

If we start up our app, you should see our Loading screen with the ActivityIndicator spinning forever. This is what we expected, because we need to determine if the user is authenticated or not to determine where to route them.

If the user is authenticated, route them to the Home screen. Otherwise, send them to the SignUp screen.

Determining if a user is authenticated

We can use Firebase to determine the authentication state of a user. Let’s add a check on our Loading screen that determines if a user is logged in or not.

import React, { Component } from "react";
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
import firebase from 'react-native-firebase';

export default class Loading extends Component {
componentDidMount() {
firebase.auth().onAuthStateChanged(user => {
this.props.navigation.navigate(user ? 'Home' : 'SignUp')
})
}

render() {
return (
<View style={styles.container}>
<Text style={{color:'#e93766', fontSize: 40}}>Loading</Text>
<ActivityIndicator color='#e93766' size="large" />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
});

We are using Firebase’s onAuthStateChanged listener to get the current auth state of the user. If they are authenticated, we route them to the Home screen. Otherwise, we send them to the SignUp screen.

Now, since we’re not logged in, you should see the Loading screen for a brief moment, and then be routed to the SignUp screen.

Signing a user up

We need to create a new user, so we can log them in! Let’s head on over to the SignUp screen and wire up our handleSignUp method.

import React, { Component } from "react";
import { StyleSheet, Text, TextInput, View, Button, TouchableOpacity } from 'react-native'
import firebase from 'react-native-firebase';
import styles from './style'

export default class signUp extends Component {
state = { email: '', password: '', errorMessage: null }
handleSignUp = () => {
firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then(() => this.props.navigation.navigate('Home'))
.catch(error => this.setState({ errorMessage: error.message }))
}

render() {
return (
<View style={styles.container}>
<Text style={{color:'#e93766', fontSize: 40}}>Sign Up</Text>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>}
<TextInput
placeholder="Email"
autoCapitalize="none"
style={styles.textInput}
onChangeText ​={email => this.setState({ email })}
value={this.state.email}
/>
<TextInput
secureTextEntry
placeholder="Password"
autoCapitalize="none"
style={styles.textInput}
onChangeText ​={password => this.setState({ password })}
value={this.state.password}
/>
<Button title="Sign Up" color="#e93766" onPress ​={this.handleSignUp}/>
<View>
<Text> Already have an account? <Text onPress ​={() => this.props.navigation.navigate('Login')} style={{color:'#e93766', fontSize: 18}}> Login </Text></Text>
</View>
</View>
)
}
}
create a new account

when a user submits the form, we createUserWithEmailAndPassword and then navigate them to the Home screen. If there is an error we catch it and display it.

Displaying the current user on the Home screen

import React from 'react';
import { StyleSheet, Platform, Image, Text, View } from 'react-native';
import firebase from 'react-native-firebase'


export default class Home extends React.Component {
state = { currentUser: null }

componentDidMount() {
const { currentUser } = firebase.auth()
this.setState({ currentUser })
}


render() {
const { currentUser } = this.state
return (
<View style={styles.container}>
<Text style={{fontSize: 20}}> Hi<Text style={{color:'#e93766', fontSize: 20}}>
{currentUser && currentUser.email}!
</Text></Text></View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})

Now, when we see the Main screen, we should see the user’s email address. If we refresh the app, we should be automatically routed to the Home screen because are already authenticated.

The last step is that we should be able to log in a user after we have already created an account!

Logging an already existing user

import React, { Component } from "react";
import { StyleSheet, Text, TextInput, View, Button } from 'react-native';
import firebase from 'react-native-firebase';
import styles from './style'

export default class Login extends Component {
state = { email: '', password: '', errorMessage: null }
handleLogin = () => {
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(() => this.props.navigation.navigate('Home'))
.catch(error => this.setState({ errorMessage: error.message }))
}

render() {
return (
<View style={styles.container}>
<Text style={{color:'#e93766', fontSize: 40}}>Login</Text>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>}
<TextInput style={styles.textInput}
autoCapitalize="none"
placeholder="Email"
onChangeText ​={email => this.setState({ email })}
value={this.state.email}
/>
<TextInput
secureTextEntry
style={styles.textInput}
autoCapitalize="none"
placeholder="Password"
onChangeText ​={password => this.setState({ password })}
value={this.state.password}
/>
<Button title="Login" color="#e93766" onPress ​={this.handleLogin} />
<View>
<Text> Don't have an account? <Text onPress ​={() => this.props.navigation.navigate('SignUp')} style={{color:'#e93766', fontSize: 18}}> Sign Up </Text></Text>
</View>
</View>
)
}
}

Awesome that’s it ! 😎 ☕️

Useful links:

  1. https://facebook.github.io/react-native/
  2. https://rnfirebase.io/
  3. https://reactnavigation.org/

Github repo: soon …

--

--

Sohad Dader

Scrum| Agile | Product Manager|product Owner| Product Metrics