DEV Community

Lukie Kang
Lukie Kang

Posted on

React Learnings from 2018: Data Persistence with Firebase

This is a post from 2018 for hooking up Firebase with React. Using knowledge gleaned from Wes Bos' React for Beginners. Its probably outdated but I wanted it on my blog for the sake of reference.

We have made a fairly clever CRUD app, where state and props are used to react and update the UI accordingly. So far our React apps have been volitile, as in if we refresh the page or close the browser we lose what we did. What would be great if there was an easy way of mirroring our state to a database. Lucky* for us then, there is!

(*By luck I actually mean thanks to all the awesome people who build such things for the rest of us to use!)

Introducing Firebase

Firebase is Real-time database from Google. It uses Websockets which allows real time changes as opposed to having to refresh via Ajax or somesuch.

First thing we need to get up Firebase, which requires a Google account. I'm going to assume you are cool with that.

Then go to firebase.google.com and select Add Project.

Give it a unique name and then create it, which will take abotu 30 seconds.

You will be presented with a landing page wit all sorts of toys, Analytics, Authentication, etc. That is quite a few blog posts worth but for now, lets go see about a Database... by clicking Database.

Choosing a Database
At time of writing there is Real-time Database and a beta Cloud Firestore as database options. Let's go with Real-time Database as we dont need anything fancy right now.

Security Rules
By default, the database will want to start in locked mode, which stops any read or writes. For now we can use test mode which allows all reads and writes. In a production App we wouldnt want to do this obviously, but it will make life easier for now.

Connection details
Now we have an empty database, how do we get it to it in our code? From the Project Overview link, you should see a Add Firebase to your Web App Button which will generate a code snippet we can use.

Kepe that code handy for a second, we first need a file in our app that lets us use that information...

All about the base.js

We want to create a file called base.js' in our src directory which will handle the database connection

It requires the following imports:

  1. Re-base, a helpful library to mirror our state
    import Rebase from "re-base"

  2. Firebase, the main library for Firebase to Databasify (I am making that a word) any other data other than state: import firebase from "firebase"

To begin using firebase we need to use the initializeApp method with the apiKey, authDomain and DatabaseURL as properties. Which we can grab from that code snippet I told you to hold onto about a minute ago.

We can put that into a const like so:

const firebaseApp = firebase.initializeApp({
    apiKey: "blah",
    authDomain: "blah",
    databaseURL: "blah",
})
Enter fullscreen mode Exit fullscreen mode

Secondly we need to setup our Rebase bindings:

const base = Rebase.createClass(firebaseApp.database())

Lastly we need to export firebaseApp as a named export: export {firebaseApp}

And base as our default: export default base;

Getting our state to mirror into our Database

Head on over to our App.js and import our base.js:

import base from '../base

Here we need to use a lifecycle method called componentDidMount. This performs a set of instructions when the component is first loaded onto the page. There is alot of lifecycle methods and worth discussing another time. But for now lets roll with the following method:

 componentDidmount(){ 
    this.ref=base.syncState(`$this.props.match.params.storeId/groceries`, {
         context: this,
         state: "groceries"
    })
}
Enter fullscreen mode Exit fullscreen mode

Lets explain that a little

this.ref - alows us to reference this particular binding should we need to do something with it later.

syncState - A rebase method. A two way binding between any property on your component's state adn any endpoint in Firebase. It takes an string argument to specify an endpoint, i.e. to which bit of the database to sync to. Plus an object of further options, context and state

For the endpoint we want to use the store we generated. We got the store ID from props, and is actually provided by React router, and the /groceries makes sure we only sync that part of the state.

context - The component we want to sync the state for.

state - The property you want to sync with Firebase.

It's a fair bit to take in, but don't be afraid to read the docs for Re-base

Thats it! It might look gnarly but thats a short amount of code to quite a powerful action. If we browse to the database on the firebase console, we should see the state/groceries mirrored there. Plus, as it is a two way sync, we can change values on either end and see the change replicate near instantly!

Doing some cleanup

There is a slight gotcha...

Everytime the component mounts, we set up the sync for a given store. However we never stop it not syncing, it will quite happily continue to watch for changes for that store till the end of time. Or till we run out of memory...

To stop this, we can use another lifecycle method, componentWillUnmount. Which runs whenever the component is closed for whatever reason. We can use that to remove our binding:

componentWillUnmount(){
    base.removeBinding(this.ref);
}
Enter fullscreen mode Exit fullscreen mode

...and thats why we needed this.ref!

Final Thoughts

I have used Mongo previously, Firebase has a pretty slick way of working too. I think there is a definite series on other Firebase uses worth doing. Probably will forget though.

Top comments (0)