visit
Both React and Firebase are technologies that have been around for a while. 2018 has seen some exciting new developments that bring the two together in a way that’s greater than the sum of the individual parts — as awesome as they already are!
React is a JavaScript front-end technology created by Facebook. You could think of React as providing a crucial piece that’s missing from the web because HTML describes documents, not application UIs. React is a simple way to define the structure of a UI and how it’s updated over time as data changes. Originally developed for web apps, the React paradigm was so successful that it has since been applied to numerous other targets: there’s React Native for mobile apps, ReactVR for virtual reality, and so on. For this discussion, we’re focusing on React for web.
Firebase is a collection of services by Google for creating the back-end of mobile and web apps. Originally an independent startup, Firebase was acquired by Google and has since been integrated with Google’s global cloud infrastructure. The centerpiece of Firebase is a database, but it also provides all the other services you need for an app: there’s authentication, file storage, and cloud functions for running code on the server.
The original Firebase product was called Realtime Database. After the Google acquisition, Firebase has been creating a next-generation database product, and it’s now available as Cloud Firestore. (As of April 2018 the service is officially still in beta, but already works very reliably.)
This article is all about the new hotness of Cloud Firestore, not the “old” Firebase database. This is important because it’s rather easy to get confused about the products even on the Firebase website.The tagline for Cloud Firestore is “Store and sync app data at global scale”. It’s fast, it’s realtime, it’s backed by Google’s auto-scaling infrastructure, and it has a nice admin UI that makes it easy to manage your data without having to memorize magic SQL incantations. It’s a true next-generation database for apps.
The only question mark is pricing. Firebase has good free and $25/month tiers, but beyond that, it’s metered: you pay by the amount of reads and writes made by users. What happens if your service gets very popular? Many people would argue that’s a nice problem to have — but regardless of that, the scalability of Google’s platform means that you won’t have to suddenly re-architect your entire back-end if usage explodes. That’s a cost reduction and risk management factor that you should take into account too. (If you’re still worried, read through this article: at the end we have some additional ideas for how to manage the Firebase pricing risk.)Enter React Studio. Created by Neonto, it’s a free application that bridges the worlds of UI design and development. You can bring in live data, import designs from tools like Sketch using our transfer plugins, add responsiveness and interactions, and build complete app flows. One click and you’ll get clean code in a fully functional React app structure (using Facebook’s scaffold).
That’s what makes React Studio a great learning tool for React programming. You can configure a fully working app, do changes in the GUI, and see how it affects the output code. When you want to go deeper, nothing stops you from jumping into a text editor and going crazy with the exported code. Thanks to integrated Git branch support, React Studio can be used to create and manage the UI even when you’re doing manual work on code in the same source tree. (We’ll have an article about that workflow soon!)Currently it’s available only for Mac. (If you need a Windows version, it’s possible as part of a customized enterprise edition — contact [email protected]. We’re super happy to do customizations, but please note that we can’t do custom development for Windows unless you’re committing to at least 10 seats on a long-term maintenance contract.)
We see a few things that were not mentioned in the above list of user-visible features:
Select your new project and go to Database. Make sure that “Cloud Firestore (Beta)” is selected using the button at the top (next to the big white “Database” header).
In Cloud Firestore, all data is stored in “documents” which are like the table rows in a traditional database. Each document must belong to a collection, which in turn is much like a table in a traditional database. Click on “Add Collection” and make one called “restaurants”:Click on “Next”. Now you’re asked to define the first document for this new collection. This step is important because it determines the type of data that your app will be storing in this collection. (It’s roughly equivalent to creating the table schema in a traditional SQL database, if that world is familiar to you. The difference is that Firebase collections don’t enforce the schema: each document can also contain other fields in addition to the ones you provide here for the first one.)
To describe a restaurant, we need a number of fields:
…And fill out a first document with these fields, again with the “string” type:
In the case of restaurants, it seemed redundant to add the “restaurant” prefix to all the fields. But here with reviews we see an advantage to this naming style, because one of the fields is named “restaurantID” rather than “review[something]”. This lets us easily glance at the fields and notice that there’s an external reference to another collection.
Our data model for the “local Yelp clone” is really simple. The two collections are entirely obvious except for that one “restaurantID” reference that ties reviews back to restaurants.Collections and documents both get automatically generated object ids — long strings with numbers and letters like x3LBcxO4JwXc2. These object ids are unique and can be used to locate any piece of data within your Cloud Firestore database.
In order to make a review that always “belongs” to a particular restaurant, all we needed to do was create that “restaurantID” field. Our client app (the one made in React Studio) will be responsible for making sure that any new reviews that users create will contain a valid document id in the “restaurantID” field. If there are somehow reviews in the collection that don’t have a value for this field, it doesn’t break anything — those reviews simply won’t show up anywhere because the client app always requests reviews as filtered by a specific restaurantID using a query. We’ll see later how that works on the React Studio side.
Enter the following security rule, as shown above:
The rules language is fairly easy to understand. We’re telling it to match all documents anywhere in this database and allow both reading and writing. This lets you get started quickly, but you shouldn’t leave it like this permanently. Instead of opening up everything for reads and writes, you should give access only as needed. For example, only the ‘reviews’ collection actually needs write access since we’re not allowing users to add restaurants in the initial version of the demo app.
Read the and make sure you understand what the client app can read and write. Securing your database is a crucial part of designing an app.Enable only Google login for now. (You could turn on the others, but they have their various quirks: some like Twitter and Facebook need API keys from the service providers, while others like email and phone don’t provide all the data we’re using in the demo like user avatar pictures. To make things simpler for now, we’ll just go with Google first.)
Firebase will show you a piece of HTML+JavaScript code. It contains the configuration we need to copy into React Studio:
React Studio doesn’t need this whole HTML enchilada of <script> tags though. All you need to copy is the stuff between curvy brackets after “var config =” (but do include the curvy brackets). In React Studio, open the Data tab, then click on “Data Plugin Setup…” On the left you’ll see a list of all data plugins in this project. Although the list shows all possible types such as Google Sheets and Generic JSON, they’re empty — the only item is under Firebase (Cloud Firestore) and it’s named “firebase-restaurantguide”. Click on that. Then click on the text area below “Firebase config (JSON)” and paste your Firebase config there, like this:
Click on “Close” to dismiss the data plugin setup sheet.
Then click on the Restaurants tab to view that data sheet, and click the “Reload data from service” button. You should see your Firebase restaurant data appear in React Studio. (If you get an error message about an index, don’t worry, it’s easy to fix — see below in the section How to add an index to your Firebase collection.) Do the same for Reviews: open the sheet and click “Reload data from service”.
That’s it! Your database is connected and we’ve verified the connection by loading data inside React Studio. You’re now ready to try how the client app feels.Click “Open in Web Browser” in the React Studio toolbar. What this does is first export a copy of the client app as a React project, then run a local web server (at the URL localhost:3000) and open that site in your default web browser. After the export completes, you should see the browser open with a copy of the Restaurants guide app, but displaying the data you entered previously in Firebase Console.
Everything should work out of the box. You can log in with any number of Google accounts and post reviews under the single restaurant that you have configured in the database. (As users sign in, their information gets added to the Users list in Firebase Console > Authentication. That’s a convenient way to see who’s using your app.)There are two important concepts that link Cloud Firestore to React Studio. The first is data sheets which are like “views” into your Firebase collections. The second is React’s properties which will be linked to fields in your Firebase documents.
Let’s first take a look at how data sheets are configured. You can create any number of data sheets in React Studio, but typically they would closely match your Cloud Firestore collections. In the Data tab, click on “Restaurants”. This displays a data sheet named, well, Restaurants:
The data sheet’s contents are loaded from Firebase, but it’s not automatic — you have to trigger it manually. (This is so that you can have consistency while designing.) Click “Reload data from service”, and you should see the data from your Firebase restaurants collection appear.
In the bottom-right corner are some interesting settings. Collection id is the name of the collection that’s associated with this data sheet. Query is a free field where you can enter queries written in the .
These queries are actually JavaScript method calls using the Cloud Firestore API. You can chain these methods with a dot, as shown in Cloud Firestore’s examples (see link above). For the Restaurants sheet, we have two query methods chained together: first orderBy(), then limit(). The orderBy() call simply ensures that data is returned alphabetically ordered by restaurant name. The limit() call has something more special going on, however. Its value is:
limit($slot('ds_numberOfRestaurants'))$slot is a special template form available for queries in React Studio. It lets you look up a data slot’s value at runtime. Data slots are top-level variables that you can define and modify within React Studio (you can find them in the Data tab under “Slots”).
In this case, the value for the limit() query is being read from a data slot named ds_numberOfRestaurants. What’s going on is that we want to allow the user to choose how many restaurants are listed in the main screen. If you look at the demo app, you can see this option in the top-right corner. So, when the user selects a value in the UI, it gets saved in a data slot. Because the Restaurants data sheet has a query that refers to the data slot, it will get reloaded whenever the data slot value updates. All the machinery to watch data slots and reload the data from Firebase is automatically generated for you — all you need to do is use the $slot syntax in a query, and React Studio takes care of the rest.
Look at the Reviews data sheet next. There’s a slightly more complex query there:
Again we see an orderBy() method call, but before that there’s a where() method that looks like this:
where("restaurantID", "==", "$slot('ds_selectedRestaurantId')")The where() query method is crucial because it lets us filter what information we want from a collection. In this case we only want reviews where the restaurantId field’s value is equal to the value of a ds_selectedRestaurantId data slot in React Studio. As discussed above, the use of the $slot syntax in a query guarantees that the data sheet will be refreshed whenever the data slot’s value is updated. In practice, what happens is that when the user clicks on a “details” button for a particular restaurant, that restaurant’s id gets saved in the data slot, which then makes the data sheet update.
Pretty simple, right? Let’s see how it’s actually done. But first a brief detour to fix a missing index, a common situation when working with Cloud Firestore queries.
When you add query methods to a data sheet, you may see an error message like the one shown here. This indicates that Cloud Firestore needs to have a composite index before the query can work.
Fortunately the Firebase developers have made it easy to fix the issue. The error message contains a link that points to the Firebase Console. You can just copy the link from React Studio’s error message, paste it into a web browser, and you’ll be taken to a screen that shows the necessary index:Just click on “Create Index”, then go back to React Studio and reload the data into the data sheet.
In the top-left corner of the canvas, you can see a list of properties like restaurantName, restaurantAddress, etc. From these names, thin blue lines point to UI elements that are linked to each property. For data linkage to work correctly, the used property names must match the document fields in your Firebase restaurants collection earlier. You can click on any element to view it in the Inspector panel on the right, and then open the Data tab to view how properties are linked.
Let’s see how the interaction is done. Click on the “Details” button in the canvas. Choose the Interact tab and you’ll see the following:
There’s a bunch of stuff going on here. The Tap interaction actually has two actions attached to it — you can tell by the numbers 1/2 at the top next to “When user taps”. The first action is “Save data”, and its target is a data slot named ds_selectedRestaurantId. (Remember that’s the same data slot that was used in the query for the Reviews data sheet.)
The value that gets saved in the data slot is taken from a component property. This part is somewhat non-obvious and requires explanation. To get the restaurant’s id that pertains to the current item, we’re accessing a property named datasheetRow.key. How does this work?
The datasheetRow property is provided by React Studio whenever a component is used within a list. It gives access to the entire contents of the row within the data sheet. Because our datasheet is sourced from Firebase, that means the datasheetRow property will simply contain the Firebase document (for a restaurant in this case).
But what’s “key”? We didn’t have such a field in Firebase. This value is actually being provided by the Cloud Firestore plugin which puts the document’s id in there. The property name “key” is special in React: it’s required for data that’s used in lists so that React knows which items are unique when the data changes. The Firestore document id neatly fulfills this role, and thus what Firestore calls “object id” becomes “key” in React.Long story short: when a component is used inside a list, you can always find the document’s id in the datasheetRow.key property.
Next click on the little “2” button to show the other action:
This action is of type “Go to” and links to the RestaurantDetails screen. Actions are chained, so when the user clicks on this button, first the value of datasheetRow.key gets saved in the data slot, then this “Go to” action gets executed.
This way, the RestaurantDetails screen is always entered in a state where the Reviews data sheet already contains only those reviews pertinent to a particular restaurant. (Remember that the query on the Reviews data sheet is the glue that makes this work.)
An interesting setting here is “Carry properties from parent component”. It’s set to the value “All”. This means that any properties from this list item will be passed on to the next screen.We can open the RestaurantDetails screen to get an idea of why that’s useful:
In the top-left corner of the canvas, we again see properties that are being used. A bunch of them are marked “carried by nav”, for example restaurantCoverImage, restaurantName, etc. These properties were simply copied over from the list item that led here.
Note that the datasheetRow property implicitly gets included in the carry, so our details screen has full access to the Firebase document’s contents. That gives us access to any additional properties that might not have been used by the list item.
Double-click on the Login Gate that’s close to the Write Review screen. Then click on the “Sign up with Google” element, and you’ll see the settings for the Firebase Login plugin displayed:
There’s a bunch of settings here. You can choose which login buttons to show, whether to save user’s info into data slots, and lastly there’s a checkbox to enable automatic sign-in for returning users. The Firebase Login element works in collusion with the Login Gate screen type. You can place this element in any Login Gate (drag it from the list of elements on the right of the canvas). The element will hook up its code generation with the Login Gate, so there’s a central place (independent of the plugin) where you can decide what happens when login is successful. Click on the Screen tab:
For the Firebase login to work correctly, it’s important that you select “Web service” login type, and choose the right plugin under the “Service” button menu.
Update January 24th 2019
We’ve released five step Youtube video series for creating a Chat app with React Studio and Firebase Cloud Firestore backend. Find the full episode playlist from below. Thanks for reading, and see you soon in the amazing world of Firebase and React Studio!