Simple Firebase/Redux Integration in React Native

EM
ITNEXT
Published in
7 min readMar 14, 2018

--

Click here to share this article on LinkedIn »

In this tutorial, we will learn how to add Redux to a React Native application and how to integrate it with Firebase.

By the end of this tutorial, you should be able to pull data from Firebase into Redux, update that data in real-time, and display that data in your screens and components.

Setup

To use this tutorial, you should have a React Native application that is up-and-running and has Firebase initialized.

Installing Libraries

We are going to use 3 Redux libraries, which you can install by typing the following in a terminal in your project directory:

npm install -S redux react-redux redux-thunk

Create Some Sample Data

Head over to the Firebase Console and add some sample data to work with.

You can use existing data if you already have it!

Basic Redux Infrastructure

Disclaimer: This is how I personally setup Redux for simple applications. Other tutorials usually say to split up the different pieces into separate files. I like to have everything in one file for convenience.

Create Redux File:

Create a new folder called redux and inside of that create a file called app-redux.js.

Import Libraries:

Inside of app-redux.js, import a few Redux libraries that we will need soon. And throw Firebase in there too, because we’ll need that eventually. :)

import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import * as firebase from 'firebase';

Setup Initial State:

Below that, create a little section of code for your initial state:

//
// Initial State...
//
const initialState = {
personData: { },
}

This data structure represents the initial state of your application. Usually you will want this to be blank or filled with default values. In our case, we are going to load the data from Firebase, so we just want an empty object to begin with.

Setup Reducer:

Create another section of code for your reducer:

//
// Reducer...
//
const reducer = (state = initialState, action) => {
return state;
}

The reducer will take an action and return a new state based on what the action tells it to do. For now, since we don’t have any actions, we will just return the state as-is.

Setup Store:

Create another section of code for your store:

//
// Store...
//
const store = createStore(reducer, applyMiddleware(thunkMiddleware));
export { store };

The store is a data store that will keep track of all your data. Notice that we passed in the reducer that we created earlier. We are also applying the thunkMiddleware, which will be useful a little later. Finally, we export the store so we can use it in other files.

Connect Your App to Redux

Now that we have the basic Redux framework setup, we need to connect it to our app. Open up your App.js and import the following. Notice that we’re importing the store that we just created.

import { Provider } from 'react-redux'
import { store } from './redux/app-redux';

Surround your app’s content with the Provider component and supply it with our store. Here’s how mine looks:

This will now give your app access to the Redux store that we created.

Connect Your Screen to Redux

Now we need to connect our individual screens up to Redux. You don’t have to do this for all of your screens — only the ones that you want to have access to Redux data.

Import Libraries:

First, import connect from react-redux:

import { connect } from 'react-redux';

Create Stub Functions:

Then, create these two functions (we will fill them in later):

const mapStateToProps = (state) => {
return { };
}
const mapDispatchToProps = (dispatch) => {
return { };
}

Change Export:

My screens were all set up to be exported like this:

export default class HomeScreen extends React.Component {

So we need to remove the export default to get this (we will export it somewhere else):

class HomeScreen extends React.Component {

Export with Connect:

Finally, at the very bottom of your file, export your class like this:

export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen);

We’re calling connect and passing in those two functions we created. Then we pass our screen to the result of that call.

Final Screen:

For reference, here is what my screen looks like:

Now your screen is connected to Redux, but we will come back later to retrieve and display the data.

Actions

Now, we will create some actions that we can use in Redux to update our data.

Standard Action:

Back in app-redux.js, create another section of code for Action Creators. Action creators get sent to your reducer and contain information about how to update the state. Here we will create an action creator that can update our state.personData object. We will also export it so it is accessible in other files.

Note: You can put any data you want in the return object. But it is a Redux convention to always have a type property.

//
// Action Creators
//
const setPersonData = (personData) => {
return {
type: "setPersonData",
value: personData
};
};
export { setPersonData };

Since action creators get sent to the reducer, we need to update the reducer to be able to handle this action. Scroll up to your reducer and update it like so:

const reducer = (state = initialState, action) => {
switch(action.type) {
case "setPersonData":
return { ...state, personData: action.value };
default:
return state;
}
}

See how we are switch-ing on action.type? That’s why we should always include a type property in our action creators.

Notice that when the type is "setPersonData", we return a new state where personData is changed to the action.value. This will update our state and anywhere in the app that is accessing that data.

Thunk:

Ordinarily, action creators can only return objects. But since we applied the thunkMiddleware, we can also have action creators that return functions. This is crucial for actions that don’t have data immediately available (such as asynchronous network calls), or for data that updates in real-time (such as Firebase realtime updates).

Let’s create another action that will watch our Firebase data in real-time.

const watchPersonData = () => {
return function(dispatch) {
firebase.database().ref("person").on("value", function(snapshot)
{
var personData = snapshot.val();
var actionSetPersonData = setPersonData(personData);
dispatch(actionSetPersonData);
}, function(error) { console.log(error); });
}
};

Here, we are returning a function that is given a dispatch as a parameter. Inside the function, we call Firebase’s realtime function .on("value") for the "person" node in our database. Any time that function is successful (which will be anytime our data is updated), we will grab the data from snapshot.val(), get a setPersonData action creator, and then dispatch that action to our reducer (which will then update the state). If the function fails, we just log the error in the console.

Sound like a lot? It is, but see how it all ties together in the next section.

PS: Don’t forget to export your new action creator!

export { setPersonData, watchPersonData };

View Data in Screen

Back in our HomeScreen.js, we need to update those functions that we initially created, mapStateToProps and mapDispatchToProps. These functions will actually add props to your screen/component so you can access them to render the data.

Before updating them, let’s import the watchPersonData action creator that we just created.

import { watchPersonData } from './../redux/app-redux';

mapStateToProps:

Now update mapStateToProps to give your screen access to state.personData:

const mapStateToProps = (state) => {
return {
personData: state.personData
};
}

This takes the state (from Redux) and creates a property in your screen called personData whose value comes from state.personData. Now, anywhere in your screen, you can display personData. Try it out!

<Text>{this.props.personData.firstName}</Text>
<Text>{this.props.personData.lastName}</Text>

mapDispatchToProps:

The only problem now is that we never started watching for data!

Update your mapDispatchToProps function to add a property to your screen called watchPersonData.

const mapDispatchToProps = (dispatch) => {
return {
watchPersonData: () => dispatch(watchPersonData())
};
}

This now adds a function property to your screen called watchPersonData that, when called, will dispatch the watchPersonData action (which then calls the Firebase API for watching data in our "person" node.

Now, in your screen’s constructor, call this.props.watchPersonData().

Test:

Test it out by running your application. You should now see the personData displayed on your screen. Go into Firebase and change the data and come back to your application. You should see the updated data!

Full Code Reference

App.js

HomeScreen.js

app-redux.js

Reference

Video Tutorial:

Redux Libraries:

--

--