Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

Firebase and React

Save for later
  • 300 min read
  • 2016-01-27 00:00:00

article-image
Firebase is a realtime database for the modern web. Data in your Firebase is stored as JSON and synchronized in realtime to every connected client.

React is a JavaScript library for creating user interfaces. It is declarative, composable, and promotes functional code. React lets you represent your UI as a function of its state.

Together they are dynamite!

In this post we will explore creating a React application with a Firebase backend. We will take a look at how we can use Firebase as a Flux store to drive our UI.

Create a project


Our app will be an SPA (Single Page Application) and we will leverage modern JavaScript tooling. We will be using npm as a package manager, babel for ES2015+ transpilation, and browserify for bundling together our scripts.

Let's get started.

$ mkdir todo && cd todo
$ npm init
$ npm install --save 
   [email protected] 
   [email protected] 
   firebase
$ npm install --save-dev 
   budo 
   babelify


We have now made a folder for our app todo. In that, we have created a new project using npm init (defaults are fine) and we have installed React, Firebase, and some other packages. I didn't mention budo before, but it is a great browserify development server.

NOTE: At the time of writing, React is at version 0.13.3. In the next major release (0.14), React itself is decoupled from the DOM rendering. In order for this blogpost not to be obsolete in a matter of weeks we use the 0.14.0-rc1 version of React. Since we intend to render DOM nodes from our React components, we also need to install the react-dom module.

React basics


Let's start by creating a basic React application. We will be making a list of TODO items.
Make a file index.js in the todo directory and open it in your favorite editor.

import React from 'react'
import ReactDOM from 'react-dom'

class TodoApp extends React.Component {
   constructor(props) {
       super(props)
       this.state = {
           todos : [
               { text : 'Brew coffee', id : 1 },
               { text : 'Drink coffee', id : 2 }
           ]
       }
   }
   render() {
       let todos = this.state.todos.map((todo) => <li key={todo.id}>{todo.text}</li>)
       return (
           <div className="todoAppWrapper">
               <ul>
                   {todos}
               </ul>
           </div>
       )
   }
}

ReactDOM.render(<TodoApp />, document.body)


Now we can run that application in a browser using budo (browserify under the hood).

$ budo index.js --live -- -t babelify


Navigate to http://localhost:9966/ and verify that you can see our two TODO items on the page.

firebase-and-react-img-0

Notice the --live parameter we pass to budo. It automatically enables livereload for the bundle. If you're not familiar with it, get familiar with it!

Set up Firebase


For setting up a new Firebase, check out the below details on the subject.

Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €14.99/month. Cancel anytime

FireFlux


To build large applications with React a good approach is to use the Flux application architecture. At the heart of Flux sits the store. A Flux store holds application state and trigger events whenever that state changes. Components listen to these events and re-render accordingly. This aligns perfectly with how Firebase works. Firebase holds your data/state and triggers events whenever something changes.

So what we are going to do is use our Firebase as a Flux store. We'll call it FireFlux :-)

Make a file fireflux.js in the todo directory and open it in your favorite editor.

import Firebase from 'firebase/lib/firebase-web'
import { EventEmitter } from 'events'

const ref = new Firebase('https://<name>.firebaseio.com/todos')
const fireflux = new EventEmitter()
fireflux.store = {
   todos : []
}
fireflux.actions = {
   addTodo : function(text) {
       ref.push({ text : text })
   },
   removeTodo : function(todo) {
       ref.child(todo.id).remove()
   }
}

ref.on('value', (snap) => {
   let val = snap.val() || []
   if (typeof val == 'object') val = Object.keys(val).map((id) => {
       let todo = val[id]
       todo.id = id
       return todo
   })
   fireflux.store.todos = val
   fireflux.emit('change')
})


export { fireflux as default }


Notice we import the firebase/lib/firebase-web library from the Firebase module. This module includes both a browser and node version of the Firebase library; we want the browser version.

The fireflux object is an EventEmitter. This means it has functionality like .on() to listen and .emit() to trigger events. We attach some additional objects: store and actions. The store will hold our todo, and the actions are just convenience functions to interact with our store.

Whenever Firebase has updated data - ref.on('value', fn) - it will update fireflux.store.todos and trigger the change event.

Let's see how we can hook this up to our React components.

import React from 'react'
import ReactDOM from 'react-dom'
import fireflux from './fireflux'

class TodoApp extends React.Component {
   constructor(props) {
       super(props)
       this.state = {
           todos : []
       }
   }
   render() {
       let todos = this.state.todos.map((todo) => {
           return (
               <li key={todo.id}>
                   <button onClick={this.removeTodo.bind(this, todo)}>done</button>
                   {todo.text}
               </li>
           )
       })
      return (
           <div className="todoAppWrapper">
               <button onClick={this.addTodo}>Add</button>
               <ul>
                   {todos}
               </ul>
           </div>
       )
   }
   addTodo() {
       let todo = window.prompt("Input your task")
       fireflux.actions.addTodo(todo)
   }
   removeTodo(todo) {
       fireflux.actions.removeTodo(todo)
   }
   componentDidMount() {
       fireflux.on('change', () => {
           this.setState({ todos : fireflux.store.todos })
       })
   }
}

ReactDOM.render(<TodoApp />, document.body)


First, take a look at TodoApp's componentDidMount. It sets up a listener for FireFlux's change event and updates its state accordingly. Calling this.setState on a React component triggers a re-render of the component.

We have also included an Add and some done buttons. They make use of fireflux.actions.* to interact with Firebase. Give them a try and notice how the interface automatically updates when you add and finish items.

firebase-and-react-img-1

Hopefully you can now hit done for the last one!

About the author


Asbjørn Enge is a software enthusiast living in Sandes, Norway. He is passionate about free software and the web. He cares about modular design, simplicity, and readability and his preferred languages are Python and JavaScript. He can be found on Twitter @asbjornenge