React and Firebase were made for each other. And with the introduction of ReactFire back in May 2014, we provided a simpler way to build apps using both technologies. Today we're announcing ReactFire 0.5.0 - the biggest update since that initial release. The update brings improved performance, a handful of bug fixes, and some extra features to simplify development.
For those who aren't familiar, ReactFire is a React mixin. The ReactFireMixin makes it dead simple to bind data stored in Firebase to a component's state. It handles both array-like and object-like data via the bindAsArray() and bindAsObject() methods, respectively.
ReactFireMixin
bindAsArray()
bindAsObject()
For example, say you have a list of messages stored in your Firebase database that looks like this:
{ "messages": { "-JqpIO567aKezufthrn8": { "uid": "barney", "text": "Welcome to Bedrock City!" }, "-JqpIP5tIy-gMbdTmIg7": { "uid": "fred", "text": "Yabba dabba doo!" } } }
You can bind the message data to your component's state by calling bindToArray() in your componentWillMount() method:
bindToArray()
componentWillMount()
var ExampleComponent = React.createClass({ mixins: [ReactFireMixin], getInitialState: function() { return { messages: [] }; }, componentWillMount: function() { var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/messages"); this.bindAsArray(ref, "messages"); }, render: function() { // ... } });
The message data is now bound to this.state.messages. Whenever messages are added, removed, updated, or moved in Firebase, those changes are reflected automatically in this.state.messages
this.state.messages
this.setState()
render()
render: function() { var messages = this.state.messages.map(function(message) { return ( <li key={ message['.key'] }>{ message.uid } says { message.text } </li> ); }); return <ul>{ messages }</ul> ; }
The 0.5.0 release is the first major upgrade to the ReactFireMixin since its initial release. The API is still just as minimal, but a lot has changed under the hood.
The initial implementation of bindAsArray() was quite simplistic. It had poor performance and did not properly handle complex Firebase queries. The new implementation provides improved performance (especially on large data sets) and works well with all Firebase queries. Best of all, no changes to your code are required to enable these improvements.
Another major change with 0.5.0 is the addition of the .key attribute. ReactFire now adds the .key attribute to every record it creates via the bindAsArray() and bindAsObject() methods. In previous versions, it was impossible to retrieve key names for bound items. The 0.5.0 release fixes this by including the key name by adding a .key attribute to each bound item.
.key
As an example, let's look again at the messages array from above. The resulting bound array stored in this.state.messages will be:
[ { ".key": "-JqpIO567aKezufthrn8", // New in version 0.5.0! "uid": "barney", "text": "Welcome to Bedrock City!" }, { ".key": "-JqpIP5tIy-gMbdTmIg7", // New in version 0.5.0! "uid": "fred", "text": "Yabba dabba doo!" } ]
The inclusion of .key makes it possible to easily write data back to Firebase to update, remove, or move a record in the array. All objects synced via bindAsObject() now include the .key attribute as well.
Finally, version 0.5.0 changes how primitive values (strings, numbers, booleans) are handled. As an example, say you have the following data in your Firebase database:
{ "foo": "bar" }
If you call bindAsObject() on the /foo/ path, previous versions bound the value as a string "bar". As of today's 0.5.0 release, the bound object now looks like this:
/foo/
"bar"
{ ".key": "foo", ".value": "bar" }
You have access to the key that was bound to (.key) as well as the bound value (.value). Primitive values bound via bindAsArray() behave in the same way with the primitive value being stored in .value. Non-primitive values (that is, regular JavaScript objects) have not changed and behave in the same in all versions, except for the addition of .key.
.value
There is a lot of excitement in the React community about ES6+, Relay, GraphQL, and ReactNative. Discussions about these topics are even ongoing in the ReactFire GitHub repo. We are following the new announcements and technologies closely. Since we use React in production at Firebase, we want the two technologies to work as well as possible together.
We've found that using the vanilla React and Firebase libraries together works great and somewhat replaces the need for an application architecture like Flux. Things like ReactFire simplify development further by providing a shorthand for a lot of common use cases. And community contributions like the recently released re-base library show how well Firebase can fit into new technologies like Relay. The future of a React + Firebase application tech stack is exciting and promising. The two technologies make it that much easier to build scalable apps in a fraction of the time they traditionally have taken. You can expect ReactFire to evolve alongside React over the course of the comings months.
re-base
The best place to get started with ReactFire is by heading over to the docs. We have a five minute quickstart, a guide which walks you through making an example app, and a full API reference with more examples of binding data via bindAsArray() and bindAsObject().
If you run across any bugs or have feature suggestions, please file them on GitHub. If you have questions about the API or how to build apps with ReactFire, post them on the Firebase Google Group.
We are excited to see what you create!
If you're like me, you're really excited about React Native, a new way to build (native!) mobile applications with JavaScript. Today, I'm happy to announce that thanks to the efforts of our developer community, Firebase and React Native now work together.
React is a view library created and maintained by Facebook. I love React for its declarative API, which makes managing changes in your views dead simple.
When you build your application's views with React, it automatically updates the UI of your application when it observes state changes in your data model. Conveniently, Firebase databases deliver a stream of realtime updates to your data model. With Firebase and React, it's effortless to create components that automatically update in realtime. The two pair beautifully together.
If you're not familiar with React — and for more details on using it with Firebase — our very own Jacob Wenger wrote this excellent introduction to Firebase and React, which explains the basics of React in more detail.
React Native is a new framework that helps you build applications for native platforms primarily with JavaScript and React. React Native for iOS was released earlier this year. The React Native components in your iOS app render directly to real, native UIKit components — it's not a web app running on a mobile device.
Here's an example of some JavaScript you might write to create a simple view, from the React Native homepage. If you're familiar with React, you'll notice how instead of declaring HTML DOM elements like <div>s and <p>s, you declare components that map directly to standard iOS platform components.
<div>
<p>
var React = require('react-native'); var { TabBarIOS, NavigatorIOS } = React; var App = React.createClass({ render: function() { return ( <TabBarIOS> <TabBarIOS.Item title="React Native" selected={true}> <NavigatorIOS initialRoute={{ title: 'React Native' }} /> </TabBarIOS.Item> </TabBarIOS> ); }, });
Did I mention this is just JavaScript? React Native also has support for ES6 syntax (shown above), and you can write your app with Flow, Facebook's static type checker for JavaScript.
Other bonuses of React Native include support for npm modules, debugging in Chrome Developer Tools, and instant reload in XCode (as in, hit Cmd-R and your app reloads in a few seconds instead of having to do full XCode rebuilds). It's a wonderful development experience.
Cmd-R
Although React Native is still in beta, it's currently being used in production in some of Facebook's apps, including its Groups app.
In short, I'm excited about React Native because it lets me write native mobile apps with the technologies I use every day as a web developer.
If you'd like to start getting your hands dirty with React Native, the official tutorial is an excellent place to start.
Once you've created your React Native app, just head to your nearest terminal and enter these magic characters to install Firebase via npm:
npm install firebase --save
Then, in your JavaScript code just softly whisper var Firebase = require('firebase'); and all the power of the Firebase JavaScript SDK and React Native will be yours!
var Firebase = require('firebase');
If you have any questions, bug reports, general commentary, or if you just want to say hi, you can find me on Twitter at @KanYang.
Thanks to Harrison Harnisch, a developer in our community, for helping to get support for WebSockets merged into React Native!
Have you ever had an app suddenly stop working when you lost your internet connection? Or perhaps you've opened an app you were using just minutes prior, only to find you have to re-download all of your data?
As a developer, you've likely tried to solve these pain points in your own apps, only to find the work required to be daunting. Wouldn't it be great if your database could just handle this for you automatically?
Today we're announcing a set of features for our iOS and Android SDKs that will allow you to build apps that work smoothly offline!
Our new SDKs support persisting your synchronized data to disk, so it's available immediately when your app starts. You can enable disk persistence with one line of code:
Firebase.getDefaultConfig().setPersistenceEnabled(true);
[Firebase defaultConfig].persistenceEnabled = YES;
Firebase.defaultConfig().persistenceEnabled = true
Our new SDKs now also let you specify data to be prefetched and kept up to date so that it will be available offline later if you need it. This keepSynced feature can be enabled on a per-path basis with one line of code:
keepSynced
ref.keepSynced(true);
[ref keepSynced:YES];
ref.keepSynced(true)
The Firebase database uses synchronization rather than request / response to move data between client and server. All read and write operations happen against a local, on-device version of your database first. Then, data is pushed and pulled from our servers behind the scenes. This design has allowed the Firebase database to compensate for network latency -- local write operations are reflected by local reads before being acknowledged by the server.
It turns out, though, that this design is also essential to a high quality offline experience. By sending all reads and writes through a local version of the database, the Firebase SDK maintains the freedom to serve that data from the best source available -- whether that’s from the network or local disk. Later, when a network connection becomes available, our SDK automatically commits local operations to the server and pulls in the latest remote updates.
We designed Firebase for offline support from the very beginning, and we've been working on it for years. Citrix has been beta testing our offline support for its iOS app Talkboard since 2013. When you draw on a canvas in Talkboard, any updates you make while offline will be saved to disk and synchronized later when you reopen the app.
We've been working on these features for a long time, and we couldn't be more excited to see what you build with them! Getting started is easy -- just check out the offline section of our guides for iOS or Android. We also have offline drawing examples for iOS and Android that can help you get started quickly.
As you're coding, we'd love to hear what you think! Please share your feedback in our Google Group or mention @Firebase on Twitter.
Many of our developers are using Firebase with a server to perform tasks like background processing, integrating with third party APIs, or handling advanced authentication requirements. Today, we're introducing Firebase Queue, a fault-tolerant multi-worker job pipeline built on Firebase.
If you're writing your server code in Node, Firebase Queue makes it easy to handle background jobs with a worker queue. We're already using it in our private backups feature, where we reliably handle hundreds of jobs per day across multiple machines.
Once you've installed firebase and firebase-queue, you can get started by creating a new Queue and passing it your Firebase reference and a processing function. This processing function specifies the data transformation that the worker performs and when called, will be passed the following four parameters:
data
progress()
resolve()
reject()
Below is a simple example of what an instance of the queue looks like:
var Queue = require('firebase-queue'), Firebase = require('firebase'); var queueRef = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/queue'); var queue = new Queue(queueRef, function(data, progress, resolve, reject) { // Read and process task data console.log(data); // Update the progress state of the task setTimeout(function() { progress(50); }, 500); // Finish the job asynchronously setTimeout(function() { resolve(); }, 1000); });
When your Queue runs, the data will be stored in Firebase under a /queue/tasks path and removed when complete. For an item in your queue called example1, the data in Firebase would look like the following:
/queue/tasks
example1
{ "queue": { "tasks": { "example1": { "_owner": "worker_1", // The worker process who owns this task "_progress": 88, // A number from 0 to 100 indicating the item’s status in the queue "_state": "in_progress", // Indicates whether the job has errored, is in progress or finished "_state_changed": 1430937731946, // Timestamp when the state was last updated "your": "data" // Original data in your task } } } }
You can push an object with some data to the /queue/tasks location in your Firebase using any Firebase client or the REST API. Workers listening at that location will automatically pick up and process the job:
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/queue/tasks"); Map task = new HashMap(); task.put("your", "data"); ref.push().setValue(task);
Firebase *ref = [[Firebase alloc] initWithUrl:@"https://<YOUR-FIREBASE-APP>.firebaseio.com/queue/tasks"]; [[ref childByAutoId] setValue:@{@"your": @"data"}];
var ref = Firebase(url: "https://<YOUR-FIREBASE-APP>.firebaseio.com/queue/tasks") ref.childByAutoId().setValue(["your": "data"])
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/queue/tasks"); ref.push({"your": "data"});
curl -X POST -d '{"your": "data"}' https://<YOUR-FIREBASE-APP>.firebaseio.com/queue/tasks.json"
If you don't want to use the default spec, you can define your own. You can also chain several specs together to create custom jobs. More details on customizing and chaining jobs can be found in the Firebase Queue README.
We have a few examples to help you get started with Firebase Queue. This gist creates a new Queue with 10 workers and a custom task task_1. In this example, the queue sanitizes chat messages to make sure they don’t contain any banned words.
task_1
When you try out firebase-queue in your app I'd like to hear what you think. Send a pull request, file an issue, or reach out to me on Twitter @drTriumph.
Ionic is an HTML5 mobile app SDK that makes it extremely simple to build native-feeling iOS and Android apps with JavaScript. It’s built on top of Cordova and uses AngularJS for its core functionality. I love learning new frameworks, and I’ve been thoroughly impressed with how easy it is to get up and running with Ionic. Since Ionic uses Angular, it’s incredibly simple to wire up with Firebase as the backend.
This screencast will help you dive into mobile web development with Ionic in less than 8 minutes. It assumes you are familiar with the basics of Angular and walks you through building a cross-platform collaborative grocery list application. Check it out below:
I’d like your feedback! If there are features you’d like to see in an upcoming screencast, send me your suggestions on Twitter at @SRobTweets.