firebaseWatcher.js See, it’s all ass-about, I have to start at the bottom right! When the app first loads, I set up a bunch of listeners. If anything is added or changed in the database, that individual object will trigger a change event, and the appropriate action will be dispatched to the store.

See, it’s all ass-about, I have to start at the bottom right! When the app first loads, I set up a bunch of listeners. If anything is added or changed in the database, that individual object will trigger a change event, and the appropriate action will be dispatched to the store. Store All of those listeners in firebaseWatcher.js fire when there’s a change, but also when they’re first bound, so this populates our store when the page loads (or when a user signs in).

All of those listeners in fire when there’s a change, but also when they’re first bound, so this populates our store when the page loads (or when a user signs in). Component The fare usual here. Lots of stateless components just turnin’ store into pixels and waiting for the user to do something. Finally a user decides to add a new student to the system and the component jumps to the ready and calls an action…

The fare usual here. Lots of stateless components just turnin’ store into pixels and waiting for the user to do something. Finally a user decides to add a new student to the system and the component jumps to the ready and calls an action… actions.js An “action”, in this case, is just a function that does something with the data it’s passed. Usually tracking an event for analytics and passing the data on to…

An “action”, in this case, is just a function that does something with the data it’s passed. Usually tracking an event for analytics and passing the data on to… firebaseActions.js This handles all the communications to Firebase. And apparently a lot like me, doesn’t pay attention to any response.

The data in Firebase is normalized (as is the store), so this file plays the role of ORM which means it’s mildly complex, but it has only one job: send data to Firebase.

Another kind of magical thing about Firebase: to remove a student from the database, and any references to that student in courses and schools all in one operation is easy. Easy I tell you.

This handles all the communications to Firebase. And apparently a lot like me, doesn’t pay attention to any response. The data in Firebase is normalized (as is the store), so this file plays the role of ORM which means it’s mildly complex, but it has only one job: send data to Firebase. Another kind of magical thing about Firebase: to remove a student from the database, and any references to that student in courses and schools all in one operation is easy. Easy I tell you. And we’re back at the start. Firebase will emit an event, firebaseWatcher.js will send an action to the store which in turn emits a change event, and the components react and re-render themselves.

So you see React and Firebase are weird and great for the same reason. You have to learn to trust the system. With React, it was learning to trust that if your components are connected to the store correctly, you only need to worry about throwing data to the store. The UI will look after itself, and do so performantly.

It’s the same with Firebase. As long as Firebase is bound to your store properly via listeners, you can just throw data at it and know that the store, and thus your components and UI, will look after themselves, and do so performantly.

And guess what, if you want multiple clients updating in real-time as centralized data changes, you’ve already done it. You can see this in Malla, open it up in two browsers and as you arrange boxes and type in one window, it updates in the other. And there was literally no extra code required to do that. Just as having two react components both updating when the store changes isn’t very special.

SHOW ME SOME CODE!

If you know React and you know Firebase you’ve probably been asleep up until now, so let’s get dirty and look at some code.

If you’re not familiar with ES6 you need to go and learn ES6.

(The data structure referred to in all this code is at the bottom of the page.)

Remember back to our example of a user adding a student record? In the database, that student is added to the global list of students (a student ‘table’, if you must) and the ID for the student is added to the user’s list of students. So to know what students to show for this user, we first look at the list of student IDs for the user, then for each of those IDs we go to the global list of students to find the whole student record.

Those two things (list of student IDs and the actual student objects) are represented by two classes that both set up listeners. One of them listens to lists, and knows when something is added or removed. But it doesn’t send data anywhere, oh no! All it does is create another listener for the actual object that was added, or removes a listener if an item is removed.

That’s excellent, I hear you say, but I WANT MORE CODE.

OK so this is how you write data to Firebase. Since we have stuff normalized, when we do something like add a new student, we need to update more than one place in the database.

If you know ImmutableJs, it’s part setIn() and part withMutations(). That is, you can write to many branches of the data structure in one atomic update() call. You simply send an object with prop/value pairs where the prop is the path to the place you want to set the value. The value itself can be a deep object.

Combine that logic with ES6 syntactical goodies like computed property names and template literals and you have the funky but glorious syntax you see from line 63 below.

More Firebase weirdness: I have the unique keys of the objects I’m creating before I send them to the database by using an empty push() which returns the key that the new thing will have.

Bonkers.

Now let’s delete some stuff. You can call a remove() method on an item in the database, but if you have other things referring to that object, you need to clean those up too, and if you don’t like things going terribly wrong in the distant future you will want to do this in a single operation. So we’ll use our good friend update() and pass in some nulls, which gives the same end result.

Scenario: Bobby Brown has kicked the bucket and we want to remove him from the database.

We remove his record in the list of students.

And the reference to them that the user has.

And the reference that the school object has.

And we must look up each of the courses Bobby was enrolled in and remove the reference to him from there.

Starting with his ID, we first get his full record from the database. About an hour ago I said that you don’t ‘read’ from Firebase, you ‘listen’. Well sometimes you just want to read, which is done by listening ‘once’, then doing something with the result in a callback.

So you see, we generate the removeData object bit-by-bit, but we send it to db.update() in one go, so the removal is still atomic.

All up, not a lot of code for what is quite a complex operation.

And that’s what I like a lot about Firebase and React. I had some awful code as I was finding my way, but as I came to understand them better, and how they could work together, I refactored again and again and at some point it all started to fall into place as quite a simple set of steps.

If you want to check out how this sits in a real app with authentication and other complexities, I’m leaving the source for Malla out in the open for the time being so go have a peruse.