Integrating Firestore to React app

Posted on March 08, 2019


Firestore is a noSQL database that you can use to store and fetch user generated data.

This tutorial will help you integrate Firestore into a React app.

But first, you need to create a new Firebase project.

Signup for Firebase project

Head over to Firebase website and click on GO TO CONSOLE. You'll be directed to create a Google account if you haven't got one already.

Next, click on Add project then write a name for your project. It can be anything you want that closely identify your application project. For this tutorial, it could be "firestore-example".

Check the boxes to agree with Firebase's terms and click on Create project, and just wait until the project is ready.

Once it does, click on continue and you'll be taken into the project dashboard.

Now the project is ready. It's time to learn about Firestore!

Activating Firestore

From the dashboard screen you are in, click on the Database left sidebar, then click on create database.

You'll be prompted to select security rules for this database. Select using test rules so that you can use it without authentication. You will need to change security rules before deploying to production, but it's okay for learning purpose.

I have a repo of this tutorial on Github here

This example code will use Bootstrap for styling and react-notifications for sending notification to users.

Integrating Firebase NPM package

Firebase has an NPM package that can be used in React application. First, you need to install the package:

You can install the package, or just fork this codesandbox for tweaking purpose.

In your src/ directory, create a new file named firebase.js with the following content:

import firebase from "firebase";

const firebaseApp = firebase.initializeApp({
  // copy and paste your firebase credential here
});

const db = firebaseApp.firestore();

export { db };

The code below will initialize a Firebase instance with the provided credential, then start a firestore instance inside the variable db. You need to include your Firebase project configuration into the initializeApp argument above. It's located in the Settings menu (Gear icon) just beside Project Overview.

The configuration would look like a JavaScript object:

{
  apiKey: "{your credential here}",
  authDomain: "{your credential here}",
  databaseURL: "{your credential here}",
  projectId: "{your credential here}",
  storageBucket: "{your credential here}",
  messagingSenderId: "{your credential here}"
}

Now Firestore is ready for saving and fetching data. Let's start with saving data first.

Saving data into Firestore

In Firestore, data is saved as a collection of documents with each document holding fields that maps to values. The structure of the data is pretty similar to JavaScript Object Notation or JSON.

To summarise, a document can hold many data, while a collection can hold many documents, and one Firestore database can hold many collections.

In order to save data into Firestore, you need to use its the db instance you have created earlier:

// Add a new document in collection "cities"
db.collection("cities").doc("LA").set({
    name: "Los Angeles",
    state: "CA",
    country: "USA"
})
.then(function() {
    console.log("Document successfully written!");
})
.catch(function(error) {
    console.error("Error writing document: ", error);
});

First select the db collection, then select a single doc then you set data into that doc.

If the collection hasn't been created yet, it will be automatically created when you call on it. The same goes for document.

Now let's see it in action on the demo code. Open the file component/Register.js and you will see the addUser function on line 25.

addUser = () => {
  const data = {
    ...this.state.formValues,
    uid: new Date().getTime()
  };

  // adding data here
  db.collection("users")
    .doc(data.uid.toString())
    .set(data)
    .then(() => {
      NotificationManager.success("A new user has been added", "Success");
      window.location = "/";
    })
    .catch(error => {
      NotificationManager.error(error.message, "Create user failed");
      this.setState({ isSubmitting: false });
    });
};

In the code above, state.formValues are being used as the key-value pair for the data, with a uid key holding millisecond values. In this example, there are two values saved to Firestore from state: name and role.

The set function can be used to add and update data.

After set is finished, chain the function with then and catch function to run when data update succeeded or failed. In this example, the app will send a notification through react-notification package and then refresh the browser, so that React will run componentDidMount from SavedList.js file, which fetch data from Firestore.

And that's all there is to saving data in Firestore. Let's see how you can fetch data from it now.

Fetching data

Fetching data in Firestore is done through the get function. You can get the whole collection, or a single document, or even set where queries to get matching documents.

Fetching a single document will return a single document, while fetching the collection and specific query will return latest snapshot from the database. What's a snapshot? In Firestore, it means an array of all the documents returned from your get function.

// get the whole collection
db.collection("cities")
.get()
.then(querySnapshot => {
  const data = querySnapshot.docs.map(doc => doc.data());
  console.log(data); // array of cities objects
});

// or get the single doc from the collection
db.collection("cities")
.doc('LA')
.get()
.then(doc => {
  const data = doc.data();
  console.log(data); // LA city object with key-value pair
});

// or get all docs matching the query
db.collection("cities")
.where("country", "==", "USA")
.get()
.then(querySnapshot => {
  const data = querySnapshot.docs.map(doc => doc.data());
  console.log(data); // array of cities objects
});

In the demo example, you will see the code fetch the whole users document and set it to state in component/SavedList.js file on line 11:

componentDidMount() {
  db.collection("users")
    .get()
    .then(querySnapshot => {
      const data = querySnapshot.docs.map(doc => doc.data());
      console.log(data);
      this.setState({ users: data });
    });
}

The code will get all document in "users" collection, then map the array of querySnapshot documents, and put its data into data variable.

After that, the data will be put into users state.

The rest of the component will take the users state and render it using map function.

Once again, here is the repo for this demo

That's all you need to know about Firestore for this section, you can check out the documentation if you're interested about what else it can do. It's very powerful and can even set listener for data changes in real time, which can be used for a real time chat application, if you want to create one.

I will write about Authentication and securing your Firestore database next.

Learning React+Firebase? You can also check out my book React Distilled for complete tutorial and exercise!

Share this:
LinkedIn
Reddit
WhatsApp

Get Free Guides