Firebase v3.0 and React Native make a great pair. react-native-firestack is a thin layer between the native JS Firebase libraries that adds support to the rest of the Google stack.
Announcing Firestack
Firebase is a fantastic, real-time Backend-as-a-Service (BaaS, for short) now run by Google. Earlier this year, Google announced a deep integration with the rest of their cloud platform, including a major update to the Firebase service.
Working with the latest iteration of the service with React Native, however, isn't fully supported. Being big fans of both React Native and Firebase, we've written a library to manage this gap and we're open-sourcing it today!
Firestack
Firestack aims to be a thin wrapper around the already fantastic Firebase JavaScript library, both providing a clean interface to the Firestack backend as well as adding support for the features the official library does not support.
This includes features up and down the Google Platform stack, including:
- authentication
-
real-time database
- With a FirebaseModule layer that works with callbacks, promises, and redux out-of-the-box
- storage
- real-time events
- remote configuration
While coverage of the entire stack is intended, we are ensuring the major features are covered first, like authentication (for both email/password and oauth-based social logins).
While we are focused on the iOS platform first, plans are in the works to cover Android development (complete with a new Android phone to prove it) ASAP (contributions HIGHLY welcomed).
Although this post assumes you have some familiarity with React, React-Native, and Firebase, our upcoming step-by-step guide build an app store-ready cross-platform, serverless react-native mobile app using
react-native-firestack
.
Getting started
In order to build a react-native mobile app, we'll need to grab the react-native-cli
tools. Let's install those globally using npm
:
npm install -g react-native-cli
When we have the cli installed, we can create a bootstrap application. Let's create an application we'll call firebaseDemo
using these cli tools.
react-native init firestackDemo
Now, the react-native-cli tools will install the dependencies it knows our application will need and nothing else. In order to install firestack, we'll need to install it as a dependency. We'll also include the latest firebase libraries using npm
. In the directory bootstrapped from the react-native init
command, let's install these dependencies:
cd firestackDemo
npm install --save react-native-firestack firebase
Next, we'll use the react-native link
command to link our project with the firestack dependency:
react-native link react-native-firestack
Building the iOS app
Due to some intricasies of XCode, we do need to make some adjustments to the generated iOS app. To do that, let's open the ios/firestackDemo.xcodeproj
file.
When XCode opens, find the Build Phases
tab on the project target settings and add a Copy files
build phase:
From there, make sure the Copy files
build phase says Frameworks
and click on the plus button:
Find the newly linked libFirestack.a
library and add it to the build phase:
And finally, make sure the Code Sign on Copy
checkbox is checked:
Lastly, due to some dependencies with XCode, firestack depends upon a build of iOS 8.0 or higher. We'll need to switch this in our application by finding the General
tab, clicking on the Deployment target
dropdown and changing it to 8.0
:
And now our iOS app is ready to go!
Building the Android app
This process isn't yet complete. We'll update this post when we have Android support ready.
Running our app
Our demo application source is included in it's entirety at the end of this post. Feel free to following along with it or copy and paste it into your project at index.ios.js
at the root directory (the firestackDemo/
directory created with the react-native init
command).
For convenience, the included demo application looks for configuration files in a config/
directory at the root of the project.
mkdir config/
We've included a demo configuration files here (url: https://gist.github.com/auser/82c9c09e3cd2e40e89f4163b46afdaab). Grab these two files and add them to the config/
directory we just created.
We'll fill in these variables with the settings from your Firebase application. You can make a Firebase application by using the Firebase console. For more details from the Firebase team, check out their docs at https://firebase.google.com/docs/web/setup.
For the purposes of demonstration, we'll set up our app using redux, but the firebase module works with callbacks and promises and does not depend upon Redux.
Let's set up our application to use Redux as a global store. We'll need to include redux-thunk
as a middleware layer. Let's install these dependencies using npm
again:
npm i --save redux react-redux redux-thunk
And let's set up our basic redux application
// Redux setup
import { applyMiddleware, combineReducers, createStore } from "redux";
import { Provider, connect } from "react-redux";
import thunk from "redux-thunk";
// ...
let reducers = {};
const middleware = applyMiddleware(thunk);
const store = createStore(combineReducers(reducers), {}, middleware);
FirestackModule
Firestack ships with several ways to work with Firebase. Since we use Redux pretty heavily, the easiest way to work with Firestack is to use the new FirestackModule
, which you can use to listen to all updates on a store using either Redux or callbacks (both will be called).
import Firestack, { FirestackModule } from "react-native-firestack";
To create a FirestackModule
, import it from Firestack and pass the firestack
instance to the module along with a firebase ref string path to the FirestackModule
:
const inst = new FirestackModule("events", { firestack });
To be as flexible as possible, you can set the store either on the firestack module or the firestack instance (needed when using Redux):
// To make the dispatch available to just this instance
inst.setStore(store);
// Make the store visible to all `FirestackModule` instances
firestack.setStore(store);
That's it. Now you just need to tell Firestack that you want to listen for subscription updates to the ref passed on the instance using the FirestackModule
instance. In our demo-case, this means listening on the path at events
.
componentWillMount() {
inst.listen();
}
Lastly, we'll need to insert the instance reducer into the store. The FirestackModule
instance exports a reducer
property, which we can use directly in our createStore()
and combineReducers()
combination.
Check out the sample application at the end of this article for more details on how to handle this specifically.
const store = createStore(combineReducers(reducers), {}, middleware)
That's it. Now our redux store is hooked up to the events. Once the component has been mounted, the Firebase events will flow through the events reducer and update the events
leaf of the store. We can treat these updates as regular updates to the Redux store with or without Firebase in the middle. Pretty snazzy, right?
Running the iOS app
In your XCode window, press "Run" (or in the terminal run react-native run-ios
) and watch your app update!
The setup is rather simple, but a complete, serverless sample app might look like the example at the bottom of the page.
Over the next several posts, we'll walk through, from start to finish how to build a complete app, from the very beginning through building an application using Firebase/Google as a backend, for both iOS and Android. We'll walk through setting up authentication, handling file storage, dealing with real-time events, in-app billing, etc. We are very excited about this library and will be updating it regularly, along with this post series.
Stay tuned and don't forget to checkout the repo and the README for more details, including all the API available. Contributions are eagerly accepted. We hope to make it a fantastic library for building production applications from the get-go. Feel free to make an issue or check out the source and try contributing (especially if you've written Android applications).
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
const env = require('./config/environment')
import Firestack from 'react-native-firestack'
import { FirestackModule } from 'react-native-firestack'
// Redux setup
import { applyMiddleware, combineReducers, createStore } from 'redux'
import { Provider, connect } from 'react-redux'
import thunk from 'redux-thunk'
const firestack = new Firestack(env.firestack);
const inst = new FirestackModule('events', {firestack})
let reducers = {
events: inst.reducer
}
const middleware = applyMiddleware(thunk);
const store = createStore(combineReducers(reducers), {}, middleware)
// firestack.setStore(store);
inst.setStore(store); // important
class firestackDemo extends Component {
componentWillMount() {
inst.listen();
}
render() {
const {events} = this.props;
const items = events.items;
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Event count: {items.length}
</Text>
</View>
);
}
}
const ConnectedfirestackDemo = connect(state => {
return {
events: state.events
}
})(firestackDemo)
class RootComponent extends Component {
render() {
return (
<Provider store={store}>
<ConnectedfirestackDemo />
</Provider>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('firestackDemo', () => RootComponent)
Contact us
If you’re stuck, have further questions, feel free to reach out to us by:
- Commenting on this post at the end of the article
- Emailing us at [email protected]
- Filling an issue on the Github repo
- Tweet at us at @fullstackreact