React Native and Firebase

Jacob Silverman
Jan 16, 2018 · 6 min read

This story describes my experience trying to do the Firebase React Native tutorial on the Firebase Official blog. TL:DR I had to stop half way because the instructions are a mess but if you’re doing the tutorial yourself you will probably find my notes useful. Or if you’re a Firebase professional maybe you can help me finish the tutorial… thanks!

Dev Environment Setup

Install Homebrew read the documentation, source Beginners Guide.

/usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Install Node.js 4.0 or higher but without npm because “installing node through Homebrew can cause problems with npm for globally installed packages”, source: fix Homebrew and npm article on GitHub.

brew install node --without-npm
echo prefix=~/.npm-packages >> ~/.npmrc
curl -L https://www.npmjs.com/install.sh | sh
export PATH="$HOME/.npm-packages/bin:$PATH"

Install nvm to manage node versions, source: GitHub instructions.

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash

Once those tools have been installed, run the following commands, source Beginners Guide.

brew install watchman
npm install -g react-native-cli
react-native init GroceryApp
atom GroceryApp
react-native run-ios

This should launch the Simulator, and you should see the boilerplate screen.

Firebase Setup

Run the following command at the root of the project to install Firebase.

npm install firebase --save

Open index.js and add the following line to the top:

import * as firebase from 'firebase';

Note that index.ios.js was deprecated in favour of one index.js file for both ios and android sometime in 2017. Now right above the component, initialize Firebase with your config values:

// Initialize Firebase
const firebaseConfig = {
apiKey: "<your-api-key>",
authDomain: "<your-auth-domain>",
databaseURL: "<your-database-url>",
storageBucket: "<your-storage-bucket>",,
};
const firebaseApp = firebase.initializeApp(firebaseConfig);

‘Add Firebase to your Web App:’ go to the Firebase Dashboard Project Settings and choose ‘Add Firebase to your Web App’. Take note of the constants to be used above, source ‘Getting started with React Native and Firebase.’

Fork in the path here, I was not sure if I should use ‘Add Firebase to your Web App’ or ‘Add Firebase to your iOS App’ to retrieve the firebase settings.. if you want to try the iOS method then choose ‘Add Firebase to your iOS App’ and go to the project root folder <your-project-name> and navigate to ios folder then open <your-project-name>.xcodeproj Look for the Bundle Identifier in the info.plist file. Not that you should not change the Bundle ID, source this StackOverflow article. You should also think about cocoapod install and update now.

ES2015 (ES6) Components

Rather than use React.createClass() to define components, let’s use classes. In index.js, let’s change the component to use a class rather than React.createClass().

class GroceryApp extends Component {
render() {
return (
<View style="{styles.container2}">
</View>
);
}
}

Note that I changed container to container2 because container was already in use from the boilerplate.

Add Styles

Create a file named styles.js and add the following code from this file. Then open index.js, and add the following line of code:

const styles = require('./styles.js')

So from the Firebase instructions when you add styles.js, the first step (after adding the empty file) is to cut the style declaration at the bottom of app.js and then paste that into style.js then below that cut/paste again from the GitHub page with stylesheet that the Firebase doc links to here. Combine the two files by cut/pasting container + welcome + instructions inside the styles declaration from the GitHub link and then renaming the second container to container2. Make sure to remove the styles variable at the bottom of the file by delete the now empty constant declaration (the one you cut/ paste from).

At this point you can check that the app still runs. It should run but I get a warning in App.js line 48 about “{styles.container2}” being a string and not an object. I have no idea why the blog article uses strings in the example. I took them out because I couldn’t find any reference to using strings in the docs. The solution is just to remove the string quotes. Then the app should run without error. Good point of note here is if you have to debug there is a remote JS debugger for the iOS simulator. On a mac, press cmd D and choose Debug JS then go to a web browser and go to the localhost:8081/debugger url to view. App should run now.

The styles are now in place. Look at the app’s component structure illustration and explanation in the official Firebase doc because I haven’t copied it here.

Break the UI into a component hierarchy

Create a folder named components. Each one of these components is stored in the components folder. The exception is App.js (or what they have GroceryApp) since it is contained in index.js (theirindex.ios.js).

Again look at the official tutorial and add ActionButton.js, ListItem.js and StatusBar.js to the components folder.

Static Mockup

In Index.js, add the imports and the code snippet from the Firebase tutorial to the top of the page. Question: why don’t they use App.js? Why Index.js here? Note that there seems to be an error here in the code snippet. I am pretty sure that these two lines:

<ListItem item="{item}" onpress="{()" ==""> {}} />
.
.
.
<ActionButton title="Add" onpress="{()" ==""> {}} />

Should be:

<ListItem item="{item}" onpress="{() ==> {}}" />
.
.
.
<ActionButton title="Add" onpress="{() ==> {}}" />

Next, create a constructor for the root component, App.js (their GroceryApp), as per the tutorial. But the tutorial doesn’t tell you where to place it. I looked in the GitHub source code for this tutorial and it looks like they put it in this order: constructor, render, _renderItem. That makes sense because _renderItem refers to DataSource and DataSource is declared in the constructor.

From the GitHub Source Code index.js differences are:

They use this const declaration..

const {
AppRegistry,
ListView,
StyleSheet,
Text,
View,
TouchableHighlight,
AlertIOS,
} = ReactNative;

They have this extra line inside the constructor…

this.itemsRef = this.getRef().child('items');

They have three extra functions below the constructor…

getRef() {
return firebaseApp.database().ref();
}
listenForItems(itemsRef) {
itemsRef.on('value', (snap) => {
// get children as an array
var items = [];
snap.forEach((child) => {
items.push({
title: child.val().title,
_key: child.key
});
});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(items)
});
});
}
componentDidMount() {
this.listenForItems(this.itemsRef);
}

They have a different render method… (mine here)

render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
<View style={styles.container2}>
</View>
</View>

theirs…

_renderItem(item) {
return (
<ListItem item=”{item}” onpress=”{() ==> {}}” />
);
}

and they have an addItem function…

_addItem() {
AlertIOS.prompt(
‘Add New Item’,
null,
[
{ text: ‘Cancel’,
onPress: () =>
console.log(‘Cancel Pressed’), style: ‘cancel’},
{ text: ‘Add’,
onPress: (text) => {
this.itemsRef.push({ title: text })
}},
],
‘plain-text’
);
}

Still wondering why do I have to remove all the string marks?

Then they have the componentDidMount that was missing…

componentDidMount() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows([{ title: 'Pizza' }])
})
}

Note they say ‘Build the app’ again now lol. Let’s give that a go!Also for some reason now my hot reloader is broken. I’m not sure how to reload the simulator (Cmd Shift R doesn’t work) so i do react-native run-ios in the terminal.

Bunch of errors follow the instructions to debug. Including the contents of return have to be all inside one view, there’s a bunch of typing errors in the Firebase tutorial that mean the html has unclosed tags. ListView is not imported from react-native so that has to be included in the import statements. Remove all the quotation marks around the strings that need to be objects. After all that I hit this pervasive error:

TypeError: undefined is not an object (evaluating ‘dataSource.rowIdentities’) I think it’s referring to [{ title: ‘Pizza’ }] that is an array of objects so I tried removing the array part but that stayed the same error. At this point would be useful to open a console and inspect what dataSource contains? But don’t know how to do that.

Along the way I ran into the Bundle Identifier error to which a bunch of solutions are described here, deleting the build folder worked for me.

I now have TypeError: undefined is not an object (evaluating ‘dataSource.rowIdentities’) the solution is to change the lowercase datasource and lowercase renderrow to quasi-camel case: dataSource and renderRow.

Jacob Silverman

Written by

Web Developer | App maker

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade